Skip to content

Commit

Permalink
Support Compound Tasks, Background Tasks and TaskIdentifier, Fixes #5517
Browse files Browse the repository at this point in the history
 and also Fixes #6534

Signed-off-by: Shimon Ben Yair <shimon.ben.yair@sap.com>
  • Loading branch information
ShimonBenYair authored and elaihau committed Dec 18, 2019
1 parent 938bc48 commit f54e970
Show file tree
Hide file tree
Showing 11 changed files with 467 additions and 32 deletions.
24 changes: 18 additions & 6 deletions packages/debug/src/browser/debug-session-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { ContextKey, ContextKeyService } from '@theia/core/lib/browser/context-k
import URI from '@theia/core/lib/common/uri';
import { EditorManager } from '@theia/editor/lib/browser';
import { QuickOpenTask } from '@theia/task/lib/browser/quick-open-task';
import { TaskService } from '@theia/task/lib/browser/task-service';
import { TaskService, TaskEndedInfo, TaskEndedTypes } from '@theia/task/lib/browser/task-service';
import { VariableResolverService } from '@theia/variable-resolver/lib/browser';
import { inject, injectable, postConstruct } from 'inversify';
import { DebugConfiguration } from '../common/debug-common';
Expand All @@ -35,6 +35,7 @@ import { DebugSessionOptions, InternalDebugSessionOptions } from './debug-sessio
import { DebugBreakpoint } from './model/debug-breakpoint';
import { DebugStackFrame } from './model/debug-stack-frame';
import { DebugThread } from './model/debug-thread';
import { TaskIdentifier } from '@theia/task/lib/common';

export interface WillStartDebugSession extends WaitUntilEvent {
}
Expand Down Expand Up @@ -410,7 +411,7 @@ export class DebugSessionManager {
* @param taskName the task name to run, see [TaskNameResolver](#TaskNameResolver)
* @return true if it allowed to continue debugging otherwise it returns false
*/
protected async runTask(workspaceFolderUri: string | undefined, taskName: string | undefined, checkErrors?: boolean): Promise<boolean> {
protected async runTask(workspaceFolderUri: string | undefined, taskName: string | TaskIdentifier | undefined, checkErrors?: boolean): Promise<boolean> {
if (!taskName) {
return true;
}
Expand All @@ -424,11 +425,22 @@ export class DebugSessionManager {
return this.doPostTaskAction(`Could not run the task '${taskName}'.`);
}

const code = await this.taskService.getExitCode(taskInfo.taskId);
if (code === 0) {
const getExitCodePromise: Promise<TaskEndedInfo> = this.taskService.getExitCode(taskInfo.taskId).then(result =>
({ taskEndedType: TaskEndedTypes.TaskExited, value: result }));
const isBackgroundTaskEndedPromise: Promise<TaskEndedInfo> = this.taskService.isBackgroundTaskEnded(taskInfo.taskId).then(result =>
({ taskEndedType: TaskEndedTypes.BackgroundTaskEnded, value: result }));

// After start running the task, we wait for the task process to exit and if it is a background task, we also wait for a feedback
// that a background task is active, as soon as one of the promises fulfills, we can continue and analyze the results.
const taskEndedInfo: TaskEndedInfo = await Promise.race([getExitCodePromise, isBackgroundTaskEndedPromise]);

if (taskEndedInfo.taskEndedType === TaskEndedTypes.BackgroundTaskEnded && taskEndedInfo.value) {
return true;
}
if (taskEndedInfo.taskEndedType === TaskEndedTypes.TaskExited && taskEndedInfo.value === 0) {
return true;
} else if (code !== undefined) {
return this.doPostTaskAction(`Task '${taskName}' terminated with exit code ${code}.`);
} else if (taskEndedInfo.taskEndedType === TaskEndedTypes.TaskExited && taskEndedInfo.value !== undefined) {
return this.doPostTaskAction(`Task '${taskName}' terminated with exit code ${taskEndedInfo.value}.`);
} else {
const signal = await this.taskService.getTerminateSignal(taskInfo.taskId);
if (signal !== undefined) {
Expand Down
6 changes: 3 additions & 3 deletions packages/debug/src/common/debug-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { TaskIdentifier } from '@theia/task/lib/common';
// tslint:disable:no-any

export type DebugViewLocation = 'default' | 'left' | 'right' | 'bottom';
Expand Down Expand Up @@ -64,10 +64,10 @@ export interface DebugConfiguration {
internalConsoleOptions?: 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart'

/** Task to run before debug session starts */
preLaunchTask?: string;
preLaunchTask?: string | TaskIdentifier;

/** Task to run after debug session ends */
postDebugTask?: string;
postDebugTask?: string | TaskIdentifier;
}
export namespace DebugConfiguration {
export function is(arg: DebugConfiguration | any): arg is DebugConfiguration {
Expand Down
37 changes: 37 additions & 0 deletions packages/task/src/browser/task-node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/********************************************************************************
* Copyright (c) 2019 SAP SE or an SAP affiliate company and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { TaskConfiguration } from '../common';

export class TaskNode {

taskId: TaskConfiguration;
childTasks: TaskNode[];
parentsID: TaskConfiguration[];

constructor(taskId: TaskConfiguration, childTasks: TaskNode[], parentsID: TaskConfiguration[]) {
this.taskId = taskId;
this.childTasks = childTasks;
this.parentsID = parentsID;
}

addChildDependency(node: TaskNode): void {
this.childTasks.push(node);
}

addParentDependency(parentId: TaskConfiguration): void {
this.parentsID.push(parentId);
}
}
48 changes: 48 additions & 0 deletions packages/task/src/browser/task-schema-updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,13 +532,61 @@ const problemMatcher = {
]
};

const taskIdentifier: IJSONSchema = {
type: 'object',
additionalProperties: true,
properties: {
type: {
type: 'string',
description: 'The task identifier.'
}
}
};

const processTaskConfigurationSchema: IJSONSchema = {
type: 'object',
required: ['type', 'label', 'command'],
properties: {
label: taskLabel,
type: defaultTaskType,
...commandAndArgs,
isBackground: {
type: 'boolean',
default: false,
description: 'Whether the executed task is kept alive and is running in the background.'
},
dependsOn: {
anyOf: [
{
type: 'string',
description: 'Another task this task depends on.'
},
taskIdentifier,
{
type: 'array',
description: 'The other tasks this task depends on.',
items: {
anyOf: [
{
type: 'string'
},
taskIdentifier
]
}
}
],
description: 'Either a string representing another task or an array of other tasks that this task depends on.'
},
dependsOrder: {
type: 'string',
enum: ['parallel', 'sequence'],
enumDescriptions: [
'Run all dependsOn tasks in parallel.',
'Run all dependsOn tasks in sequence.'
],
default: 'parallel',
description: 'Determines the order of the dependsOn tasks for this task. Note that this property is not recursive.'
},
windows: {
type: 'object',
description: 'Windows specific command configuration that overrides the command, args, and options',
Expand Down
Loading

0 comments on commit f54e970

Please sign in to comment.