Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support preLaunchTask and postDebugTask #6247

Merged
merged 1 commit into from
Oct 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/debug/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@theia/userstorage": "^0.11.0",
"@theia/variable-resolver": "^0.11.0",
"@theia/workspace": "^0.11.0",
"@theia/task": "^0.11.0",
"@types/p-debounce": "^1.0.1",
"jsonc-parser": "^2.0.2",
"mkdirp": "^0.5.0",
Expand Down
121 changes: 97 additions & 24 deletions packages/debug/src/browser/debug-session-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,25 @@

// tslint:disable:no-any

import { injectable, inject, postConstruct } from 'inversify';
import { Emitter, Event, DisposableCollection, MessageService, WaitUntilEvent, ProgressService } from '@theia/core';
import { DisposableCollection, Emitter, Event, MessageService, ProgressService, WaitUntilEvent } from '@theia/core';
import { LabelProvider } from '@theia/core/lib/browser';
import { ContextKey, ContextKeyService } from '@theia/core/lib/browser/context-key-service';
import URI from '@theia/core/lib/common/uri';
import { EditorManager } from '@theia/editor/lib/browser';
import { ContextKeyService, ContextKey } from '@theia/core/lib/browser/context-key-service';
import { QuickOpenTask } from '@theia/task/lib/browser/quick-open-task';
import { TaskService } 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';
import { DebugError, DebugService } from '../common/debug-service';
import { DebugState, DebugSession } from './debug-session';
import { DebugSessionFactory, DebugSessionContributionRegistry } from './debug-session-contribution';
import { DebugThread } from './model/debug-thread';
import { DebugStackFrame } from './model/debug-stack-frame';
import { DebugBreakpoint } from './model/debug-breakpoint';
import { BreakpointManager } from './breakpoint/breakpoint-manager';
import URI from '@theia/core/lib/common/uri';
import { VariableResolverService } from '@theia/variable-resolver/lib/browser';
import { DebugConfigurationManager } from './debug-configuration-manager';
import { DebugSession, DebugState } from './debug-session';
import { DebugSessionContributionRegistry, DebugSessionFactory } from './debug-session-contribution';
import { DebugSessionOptions, InternalDebugSessionOptions } from './debug-session-options';
import { DebugConfiguration } from '../common/debug-common';
import { DebugBreakpoint } from './model/debug-breakpoint';
import { DebugStackFrame } from './model/debug-stack-frame';
import { DebugThread } from './model/debug-thread';

export interface WillStartDebugSession extends WaitUntilEvent {
}
Expand Down Expand Up @@ -127,6 +130,15 @@ export class DebugSessionManager {
@inject(ContextKeyService)
protected readonly contextKeyService: ContextKeyService;

@inject(TaskService)
protected readonly taskService: TaskService;

@inject(DebugConfigurationManager)
protected readonly debugConfigurationManager: DebugConfigurationManager;

@inject(QuickOpenTask)
protected readonly quickOpenTask: QuickOpenTask;

protected debugTypeKey: ContextKey<string>;
protected inDebugModeKey: ContextKey<boolean>;

Expand All @@ -142,23 +154,32 @@ export class DebugSessionManager {
}

async start(options: DebugSessionOptions): Promise<DebugSession | undefined> {
try {
return this.progressService.withProgress('Start...', 'debug', async () => {
return this.progressService.withProgress('Start...', 'debug', async () => {
try {
await this.fireWillStartDebugSession();
const resolved = await this.resolveConfiguration(options);

// preLaunchTask isn't run in case of auto restart as well as postDebugTask
if (!options.configuration.__restart) {
const taskRun = await this.runTask(options.workspaceFolderUri, resolved.configuration.preLaunchTask, true);
if (!taskRun) {
return undefined;
}
}

const sessionId = await this.debug.createDebugSession(resolved.configuration);
return this.doStart(sessionId, resolved);
});
} catch (e) {
if (DebugError.NotFound.is(e)) {
this.messageService.error(`The debug session type "${e.data.type}" is not supported.`);
return undefined;
}
} catch (e) {
if (DebugError.NotFound.is(e)) {
this.messageService.error(`The debug session type "${e.data.type}" is not supported.`);
return undefined;
}

this.messageService.error('There was an error starting the debug session, check the logs for more details.');
console.error('Error starting the debug session', e);
throw e;
}
this.messageService.error('There was an error starting the debug session, check the logs for more details.');
console.error('Error starting the debug session', e);
throw e;
}
});
}

protected async fireWillStartDebugSession(): Promise<void> {
Expand Down Expand Up @@ -214,12 +235,14 @@ export class DebugSessionManager {
this.updateCurrentSession(session);
});
session.onDidChangeBreakpoints(uri => this.fireDidChangeBreakpoints({ session, uri }));
session.on('terminated', event => {
session.on('terminated', async event => {
const restart = event.body && event.body.restart;
if (restart) {
// postDebugTask isn't run in case of auto restart as well as preLaunchTask
this.doRestart(session, restart);
tolusha marked this conversation as resolved.
Show resolved Hide resolved
} else {
session.terminate();
await this.runTask(session.options.workspaceFolderUri, session.configuration.postDebugTask);
}
});
session.on('exited', () => this.destroy(session.id));
Expand Down Expand Up @@ -374,4 +397,54 @@ export class DebugSessionManager {
return origin && new DebugBreakpoint(origin, this.labelProvider, this.breakpoints, this.editorManager);
}

/**
* Runs the given tasks.
* @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> {
if (!taskName) {
return true;
}

const taskInfo = await this.taskService.runWorkspaceTask(workspaceFolderUri, taskName);
if (!checkErrors) {
return true;
}

if (!taskInfo) {
return this.doPostTaskAction(`Could not run the task '${taskName}'.`);
}

const code = await this.taskService.getExitCode(taskInfo.taskId);
if (code === 0) {
return true;
} else if (code !== undefined) {
return this.doPostTaskAction(`Task '${taskName}' terminated with exit code ${code}.`);
} else {
const signal = await this.taskService.getTerminateSignal(taskInfo.taskId);
if (signal !== undefined) {
return this.doPostTaskAction(`Task '${taskName}' terminated by signal ${signal}.`);
} else {
return this.doPostTaskAction(`Task '${taskName}' terminated for unknown reason.`);
}
}
}

protected async doPostTaskAction(errorMessage: string): Promise<boolean> {
const actions = ['Open launch.json', 'Cancel', 'Configure Task', 'Debug Anyway'];
const result = await this.messageService.error(errorMessage, ...actions);
switch (result) {
case actions[0]: // open launch.json
this.debugConfigurationManager.openConfiguration();
return false;
case actions[1]: // cancel
return false;
case actions[2]: // configure tasks
this.quickOpenTask.configure();
return false;
default: // continue debugging
return true;
}
}
}
6 changes: 6 additions & 0 deletions packages/debug/src/common/debug-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ export interface DebugConfiguration {

/** default: neverOpen */
internalConsoleOptions?: 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart'

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

/** Task to run after debug session ends */
postDebugTask?: string;
}
export namespace DebugConfiguration {
export function is(arg: DebugConfiguration | any): arg is DebugConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,16 +170,18 @@ export abstract class AbstractVSCodeDebugAdapterContribution implements DebugAda
};
properties['preLaunchTask'] = {
anyOf: [taskSchema, {
type: ['string', 'null'],
type: ['string'],
}],
default: '',
defaultSnippets: [{ body: { task: '', type: '' } }],
tolusha marked this conversation as resolved.
Show resolved Hide resolved
description: nls.localize('debugPrelaunchTask', 'Task to run before debug session starts.')
};
properties['postDebugTask'] = {
anyOf: [taskSchema, {
type: ['string', 'null'],
type: ['string', ],
tolusha marked this conversation as resolved.
Show resolved Hide resolved
}],
default: '',
defaultSnippets: [{ body: { task: '', type: '' } }],
description: nls.localize('debugPostDebugTask', 'Task to run after debug session ends.')
};
properties['internalConsoleOptions'] = INTERNAL_CONSOLE_OPTIONS_SCHEMA;
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,14 +493,14 @@ export class TheiaPluginScanner implements PluginScanner {
};
properties['preLaunchTask'] = {
anyOf: [taskSchema, {
type: ['string', 'null'],
type: ['string'],
}],
default: '',
description: nls.localize('debugPrelaunchTask', 'Task to run before debug session starts.')
};
properties['postDebugTask'] = {
anyOf: [taskSchema, {
type: ['string', 'null'],
type: ['string'],
}],
default: '',
description: nls.localize('debugPostDebugTask', 'Task to run after debug session ends.')
Expand Down
32 changes: 14 additions & 18 deletions packages/task/src/browser/quick-open-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import { TaskInfo, TaskConfiguration } from '../common/task-protocol';
import { TaskDefinitionRegistry } from './task-definition-registry';
import URI from '@theia/core/lib/common/uri';
import { TaskActionProvider } from './task-action-provider';
import { LabelProvider, QuickOpenHandler, QuickOpenService, QuickOpenOptions } from '@theia/core/lib/browser';
import { QuickOpenHandler, QuickOpenService, QuickOpenOptions } from '@theia/core/lib/browser';
import { WorkspaceService } from '@theia/workspace/lib/browser';
import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
import { QuickOpenModel, QuickOpenItem, QuickOpenActionProvider, QuickOpenMode, QuickOpenGroupItem, QuickOpenGroupItemOptions } from '@theia/core/lib/common/quick-open-model';
import { TaskNameResolver } from './task-name-resolver';

@injectable()
export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
Expand All @@ -44,15 +45,15 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
@inject(TaskActionProvider)
protected readonly taskActionProvider: TaskActionProvider;

@inject(LabelProvider)
protected readonly labelProvider: LabelProvider;

@inject(WorkspaceService)
protected readonly workspaceService: WorkspaceService;

@inject(TaskDefinitionRegistry)
protected readonly taskDefinitionRegistry: TaskDefinitionRegistry;

@inject(TaskNameResolver)
protected readonly taskNameResolver: TaskNameResolver;

/** Initialize this quick open model with the tasks. */
async init(): Promise<void> {
const recentTasks = this.taskService.recentTasks;
Expand All @@ -67,7 +68,7 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
const item = new TaskRunQuickOpenItem(task, this.taskService, isMulti, {
groupLabel: index === 0 ? 'recently used tasks' : undefined,
showBorder: false
});
}, this.taskNameResolver);
item['taskDefinitionRegistry'] = this.taskDefinitionRegistry;
return item;
}),
Expand All @@ -79,7 +80,7 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
? false
: index === 0 ? true : false
)
});
}, this.taskNameResolver);
item['taskDefinitionRegistry'] = this.taskDefinitionRegistry;
return item;
}),
Expand All @@ -91,7 +92,7 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
? false
: index === 0 ? true : false
)
});
}, this.taskNameResolver);
item['taskDefinitionRegistry'] = this.taskDefinitionRegistry;
return item;
})
Expand Down Expand Up @@ -176,12 +177,12 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
const { filteredConfiguredTasks, filteredProvidedTasks } = this.getFilteredTasks([], configuredTasks, providedTasks);
this.items.push(
...filteredConfiguredTasks.map((task, index) => {
const item = new TaskConfigureQuickOpenItem(task, this.taskService, this.labelProvider, this.workspaceService, isMulti);
const item = new TaskConfigureQuickOpenItem(task, this.taskService, this.taskNameResolver, this.workspaceService, isMulti);
item['taskDefinitionRegistry'] = this.taskDefinitionRegistry;
return item;
}),
...filteredProvidedTasks.map((task, index) => {
const item = new TaskConfigureQuickOpenItem(task, this.taskService, this.labelProvider, this.workspaceService, isMulti);
const item = new TaskConfigureQuickOpenItem(task, this.taskService, this.taskNameResolver, this.workspaceService, isMulti);
item['taskDefinitionRegistry'] = this.taskDefinitionRegistry;
return item;
}),
Expand Down Expand Up @@ -244,6 +245,7 @@ export class TaskRunQuickOpenItem extends QuickOpenGroupItem {
protected taskService: TaskService,
protected isMulti: boolean,
protected readonly options: QuickOpenGroupItemOptions,
protected readonly taskNameResolver: TaskNameResolver,
) {
super(options);
}
Expand All @@ -253,10 +255,7 @@ export class TaskRunQuickOpenItem extends QuickOpenGroupItem {
}

getLabel(): string {
if (this.taskDefinitionRegistry && !!this.taskDefinitionRegistry.getDefinition(this.task)) {
return `${this.task.source}: ${this.task.label}`;
}
return `${this.task.type}: ${this.task.label}`;
return this.taskNameResolver.resolve(this.task);
}

getGroupLabel(): string {
Expand Down Expand Up @@ -323,7 +322,7 @@ export class TaskConfigureQuickOpenItem extends QuickOpenGroupItem {
constructor(
protected readonly task: TaskConfiguration,
protected readonly taskService: TaskService,
protected readonly labelProvider: LabelProvider,
protected readonly taskNameResolver: TaskNameResolver,
protected readonly workspaceService: WorkspaceService,
protected readonly isMulti: boolean
) {
Expand All @@ -333,10 +332,7 @@ export class TaskConfigureQuickOpenItem extends QuickOpenGroupItem {
}

getLabel(): string {
if (this.taskDefinitionRegistry && !!this.taskDefinitionRegistry.getDefinition(this.task)) {
return `${this.task.source}: ${this.task.label}`;
}
return `${this.task.type}: ${this.task.label}`;
return this.taskNameResolver.resolve(this.task);
}

getDescription(): string {
Expand Down
3 changes: 2 additions & 1 deletion packages/task/src/browser/task-configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ export class TaskConfigurations implements Disposable {
}
return {
...config,
_source: rootFolderUri
_source: rootFolderUri,
_scope: rootFolderUri
};
});
this.rawTaskConfigurations.set(rootFolderUri, tasks);
Expand Down
2 changes: 2 additions & 0 deletions packages/task/src/browser/task-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { TaskConfigurationManager } from './task-configuration-manager';
import { bindTaskPreferences } from './task-preferences';
import '../../src/browser/style/index.css';
import './tasks-monaco-contribution';
import { TaskNameResolver } from './task-name-resolver';

export default new ContainerModule(bind => {
bind(TaskFrontendContribution).toSelf().inSingletonScope();
Expand Down Expand Up @@ -71,6 +72,7 @@ export default new ContainerModule(bind => {
bind(TaskResolverRegistry).toSelf().inSingletonScope();
bindContributionProvider(bind, TaskContribution);
bind(TaskSchemaUpdater).toSelf().inSingletonScope();
bind(TaskNameResolver).toSelf().inSingletonScope();

bindProcessTaskModule(bind);
bindTaskPreferences(bind);
Expand Down
Loading