@theia/task 1.73.0-next.9 → 1.73.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/task-configurations.d.ts +2 -0
- package/lib/browser/task-configurations.d.ts.map +1 -1
- package/lib/browser/task-configurations.js +9 -3
- package/lib/browser/task-configurations.js.map +1 -1
- package/lib/browser/task-problem-matcher-registry.d.ts +2 -0
- package/lib/browser/task-problem-matcher-registry.d.ts.map +1 -1
- package/lib/browser/task-problem-matcher-registry.js +7 -1
- package/lib/browser/task-problem-matcher-registry.js.map +1 -1
- package/lib/browser/task-problem-pattern-registry.d.ts +2 -0
- package/lib/browser/task-problem-pattern-registry.d.ts.map +1 -1
- package/lib/browser/task-problem-pattern-registry.js +7 -1
- package/lib/browser/task-problem-pattern-registry.js.map +1 -1
- package/lib/browser/task-service.js +15 -14
- package/lib/browser/task-service.js.map +1 -1
- package/lib/browser/task-terminal-widget-manager.d.ts +1 -7
- package/lib/browser/task-terminal-widget-manager.d.ts.map +1 -1
- package/lib/browser/task-terminal-widget-manager.js +6 -34
- package/lib/browser/task-terminal-widget-manager.js.map +1 -1
- package/lib/node/task-server.js +1 -1
- package/lib/node/task-server.js.map +1 -1
- package/lib/node/task-server.slow-spec.js +49 -1
- package/lib/node/task-server.slow-spec.js.map +1 -1
- package/package.json +13 -14
- package/src/browser/task-configurations.ts +8 -4
- package/src/browser/task-problem-matcher-registry.ts +6 -2
- package/src/browser/task-problem-pattern-registry.ts +7 -2
- package/src/browser/task-service.ts +15 -15
- package/src/browser/task-terminal-widget-manager.ts +7 -30
- package/src/node/task-server.slow-spec.ts +56 -1
- package/src/node/task-server.ts +1 -1
|
@@ -26,7 +26,7 @@ import { EditorManager } from '@theia/editor/lib/browser';
|
|
|
26
26
|
import { ProblemManager } from '@theia/markers/lib/browser/problem/problem-manager';
|
|
27
27
|
import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
|
|
28
28
|
import { TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget';
|
|
29
|
-
import { TerminalWidgetFactoryOptions } from '@theia/terminal/lib/browser/terminal-widget-impl';
|
|
29
|
+
import { TerminalWidgetFactoryOptions, nextTerminalCreationToken } from '@theia/terminal/lib/browser/terminal-widget-impl';
|
|
30
30
|
import { VariableResolverService } from '@theia/variable-resolver/lib/browser';
|
|
31
31
|
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
|
|
32
32
|
import { WorkspaceTrustService } from '@theia/workspace/lib/browser';
|
|
@@ -121,7 +121,7 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
121
121
|
@inject(TaskServer)
|
|
122
122
|
protected readonly taskServer: TaskServer;
|
|
123
123
|
|
|
124
|
-
@inject(ILogger) @named('task')
|
|
124
|
+
@inject(ILogger) @named('task:TaskService')
|
|
125
125
|
protected readonly logger: ILogger;
|
|
126
126
|
|
|
127
127
|
@inject(WidgetManager)
|
|
@@ -338,7 +338,7 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
338
338
|
} else if (event.signal !== undefined) {
|
|
339
339
|
this.messageService.info(nls.localize('theia/task/taskTerminatedBySignal', "Task '{0}' was terminated by signal {1}.", taskIdentifier, event.signal));
|
|
340
340
|
} else {
|
|
341
|
-
|
|
341
|
+
this.logger.error('Invalid TaskExitedEvent received, neither code nor signal is set.');
|
|
342
342
|
}
|
|
343
343
|
});
|
|
344
344
|
}
|
|
@@ -588,7 +588,7 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
588
588
|
return this.runCompoundTask(token, task, runTaskOption);
|
|
589
589
|
} else {
|
|
590
590
|
return this.runTask(task, runTaskOption).catch(error => {
|
|
591
|
-
|
|
591
|
+
this.logger.error('Error at launching task', error);
|
|
592
592
|
return undefined;
|
|
593
593
|
});
|
|
594
594
|
}
|
|
@@ -606,12 +606,12 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
606
606
|
const rootNode = new TaskNode(task, [], []);
|
|
607
607
|
this.detectDirectedAcyclicGraph(task, rootNode, tasks);
|
|
608
608
|
} catch (error) {
|
|
609
|
-
|
|
609
|
+
this.logger.error(`Error at launching task '${task.label}'`, error);
|
|
610
610
|
this.messageService.error(error.message);
|
|
611
611
|
return undefined;
|
|
612
612
|
}
|
|
613
613
|
return this.runTasksGraph(task, tasks, option).catch(error => {
|
|
614
|
-
|
|
614
|
+
this.logger.error(`Error at launching task '${task.label}'`, error);
|
|
615
615
|
return undefined;
|
|
616
616
|
});
|
|
617
617
|
}
|
|
@@ -759,9 +759,9 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
759
759
|
if (!(await this.requestWorkspaceTrust())) {
|
|
760
760
|
return;
|
|
761
761
|
}
|
|
762
|
-
|
|
762
|
+
this.logger.debug('entering runTask');
|
|
763
763
|
const releaseLock = await this.taskStartingLock.acquire();
|
|
764
|
-
|
|
764
|
+
this.logger.debug('got lock');
|
|
765
765
|
|
|
766
766
|
try {
|
|
767
767
|
// resolve problemMatchers
|
|
@@ -779,11 +779,11 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
779
779
|
const taskConfig = taskInfo.config;
|
|
780
780
|
return this.taskDefinitionRegistry.compareTasks(taskConfig, task);
|
|
781
781
|
});
|
|
782
|
-
|
|
782
|
+
this.logger.debug(`running task ${JSON.stringify(task)}, already running = ${!!matchedRunningTaskInfo}`);
|
|
783
783
|
|
|
784
784
|
if (matchedRunningTaskInfo) { // the task is active
|
|
785
785
|
releaseLock();
|
|
786
|
-
|
|
786
|
+
this.logger.debug('released lock');
|
|
787
787
|
const taskName = this.taskNameResolver.resolve(task);
|
|
788
788
|
const terminalId = matchedRunningTaskInfo.terminalId;
|
|
789
789
|
if (terminalId) {
|
|
@@ -805,10 +805,10 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
805
805
|
return this.restartTask(matchedRunningTaskInfo, option);
|
|
806
806
|
}
|
|
807
807
|
} else { // run task as the task is not active
|
|
808
|
-
|
|
808
|
+
this.logger.debug('task about to start');
|
|
809
809
|
const taskInfo = await this.doRunTask(task, option);
|
|
810
810
|
releaseLock();
|
|
811
|
-
|
|
811
|
+
this.logger.debug('release lock 2');
|
|
812
812
|
return taskInfo;
|
|
813
813
|
}
|
|
814
814
|
} catch (e) {
|
|
@@ -911,7 +911,7 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
911
911
|
return this.runTasksGraph(task, tasks, {
|
|
912
912
|
customization: { ...taskCustomization, ...{ problemMatcher: resolvedMatchers } }
|
|
913
913
|
}).catch(error => {
|
|
914
|
-
|
|
914
|
+
this.logger.info(error.message);
|
|
915
915
|
return undefined;
|
|
916
916
|
});
|
|
917
917
|
}
|
|
@@ -1083,7 +1083,7 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
1083
1083
|
const selectedText: string = this.editorManager.currentEditor.editor.document.getText(selectedRange).trimRight() + '\n';
|
|
1084
1084
|
let terminal = this.terminalService.lastUsedTerminal;
|
|
1085
1085
|
if (!terminal || terminal.kind !== 'user' || (await terminal.hasChildProcesses())) {
|
|
1086
|
-
terminal = <TerminalWidget>await this.terminalService.newTerminal(<TerminalWidgetFactoryOptions>{ created:
|
|
1086
|
+
terminal = <TerminalWidget>await this.terminalService.newTerminal(<TerminalWidgetFactoryOptions>{ created: nextTerminalCreationToken() });
|
|
1087
1087
|
await terminal.start();
|
|
1088
1088
|
this.terminalService.open(terminal);
|
|
1089
1089
|
}
|
|
@@ -1109,7 +1109,7 @@ export class TaskService implements TaskConfigurationClient {
|
|
|
1109
1109
|
const { taskId } = taskInfo;
|
|
1110
1110
|
// Create / find a terminal widget to display an execution output of a task that was launched as a command inside a shell.
|
|
1111
1111
|
const widget = await this.taskTerminalWidgetManager.open({
|
|
1112
|
-
created:
|
|
1112
|
+
created: nextTerminalCreationToken(),
|
|
1113
1113
|
id: this.getTerminalWidgetId(terminalId),
|
|
1114
1114
|
title: nls.localizeByDefault('Task: {0}', taskInfo.config.label || nls.localize('theia/task/taskIdLabel', '#{0}', taskId)),
|
|
1115
1115
|
destroyTermOnClose: true,
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
18
|
-
import {
|
|
18
|
+
import { WidgetOpenerOptions } from '@theia/core/lib/browser';
|
|
19
19
|
import { TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget';
|
|
20
20
|
import { TerminalWidgetFactoryOptions } from '@theia/terminal/lib/browser/terminal-widget-impl';
|
|
21
21
|
import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
|
|
@@ -25,9 +25,6 @@ import { TaskDefinitionRegistry } from './task-definition-registry';
|
|
|
25
25
|
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
|
|
26
26
|
import URI from '@theia/core/lib/common/uri';
|
|
27
27
|
import { nls } from '@theia/core';
|
|
28
|
-
import { TerminalManagerWidget } from '@theia/terminal-manager/lib/browser/terminal-manager-widget';
|
|
29
|
-
import { TerminalManagerFrontendViewContribution } from '@theia/terminal-manager/lib/browser/terminal-manager-frontend-view-contribution';
|
|
30
|
-
import { TerminalManagerPreferences } from '@theia/terminal-manager/lib/browser/terminal-manager-preferences';
|
|
31
28
|
|
|
32
29
|
export interface TaskTerminalWidget extends TerminalWidget {
|
|
33
30
|
readonly kind: 'task';
|
|
@@ -71,9 +68,6 @@ export namespace TaskTerminalWidgetOpenerOptions {
|
|
|
71
68
|
@injectable()
|
|
72
69
|
export class TaskTerminalWidgetManager {
|
|
73
70
|
|
|
74
|
-
@inject(ApplicationShell)
|
|
75
|
-
protected readonly shell: ApplicationShell;
|
|
76
|
-
|
|
77
71
|
@inject(TaskDefinitionRegistry)
|
|
78
72
|
protected readonly taskDefinitionRegistry: TaskDefinitionRegistry;
|
|
79
73
|
|
|
@@ -89,15 +83,6 @@ export class TaskTerminalWidgetManager {
|
|
|
89
83
|
@inject(WorkspaceService)
|
|
90
84
|
protected readonly workspaceService: WorkspaceService;
|
|
91
85
|
|
|
92
|
-
@inject(TerminalManagerPreferences)
|
|
93
|
-
protected readonly preferences: TerminalManagerPreferences;
|
|
94
|
-
|
|
95
|
-
@inject(WidgetManager)
|
|
96
|
-
protected readonly widgetManager: WidgetManager;
|
|
97
|
-
|
|
98
|
-
@inject(TerminalManagerFrontendViewContribution)
|
|
99
|
-
protected readonly terminalManagerViewContribution: TerminalManagerFrontendViewContribution;
|
|
100
|
-
|
|
101
86
|
@postConstruct()
|
|
102
87
|
protected init(): void {
|
|
103
88
|
this.taskWatcher.onTaskExit((event: TaskExitedEvent) => {
|
|
@@ -154,14 +139,7 @@ export class TaskTerminalWidgetManager {
|
|
|
154
139
|
}
|
|
155
140
|
|
|
156
141
|
const { isNew, widget } = await this.getWidgetToRunTask(factoryOptions, openerOptions);
|
|
157
|
-
|
|
158
|
-
if (isNew && isTreeMode) {
|
|
159
|
-
const terminalManagerWidget = await this.widgetManager.getOrCreateWidget<TerminalManagerWidget>(TerminalManagerWidget.ID);
|
|
160
|
-
terminalManagerWidget.addTerminalToTasksPage(widget);
|
|
161
|
-
widget.resetTerminal();
|
|
162
|
-
await this.terminalManagerViewContribution.openView({ reveal: true });
|
|
163
|
-
} else if (isNew) {
|
|
164
|
-
this.shell.addWidget(widget, { area: openerOptions.widgetOptions ? openerOptions.widgetOptions.area : 'bottom' });
|
|
142
|
+
if (isNew) {
|
|
165
143
|
widget.resetTerminal();
|
|
166
144
|
} else {
|
|
167
145
|
if (factoryOptions.title) {
|
|
@@ -171,14 +149,13 @@ export class TaskTerminalWidgetManager {
|
|
|
171
149
|
widget.clearOutput();
|
|
172
150
|
}
|
|
173
151
|
}
|
|
174
|
-
this.terminalService.open(widget, openerOptions);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
) {
|
|
152
|
+
await this.terminalService.open(widget, openerOptions);
|
|
153
|
+
const command = taskInfo && ProcessTaskInfo.is(taskInfo) ? taskInfo.command : undefined;
|
|
154
|
+
if (TaskTerminalWidgetOpenerOptions.echoExecutedCommand(openerOptions) && command && command.length > 0) {
|
|
178
155
|
if (widget.commandHistoryState) {
|
|
179
|
-
widget.
|
|
156
|
+
widget.write('\x1b]133;prompt_started\x07');
|
|
180
157
|
}
|
|
181
|
-
widget.writeLine('\x1b[1m> ' + nls.localizeByDefault('Executing task: {0}',
|
|
158
|
+
widget.writeLine('\x1b[1m> ' + nls.localizeByDefault('Executing task: {0}', command) + ' <\x1b[0m\n');
|
|
182
159
|
}
|
|
183
160
|
return widget;
|
|
184
161
|
}
|
|
@@ -111,7 +111,7 @@ describe('Task server / back-end', function (): void {
|
|
|
111
111
|
setup.connectionProvider.listen(`${terminalsPath}/${terminalId}`, (path, channel) => {
|
|
112
112
|
channel.onMessage(e => stringBuffer.push(e().readString()));
|
|
113
113
|
channel.onError(reject);
|
|
114
|
-
|
|
114
|
+
// onClose is not used to reject: the server now closes the channel after process exit (expected behavior).
|
|
115
115
|
}, false);
|
|
116
116
|
stringBuffer.onData(currentMessage => {
|
|
117
117
|
// Instead of waiting for one message from the terminal, we wait for several ones as the very first message can be something unexpected.
|
|
@@ -359,6 +359,52 @@ describe('Task server / back-end', function (): void {
|
|
|
359
359
|
expect(exitStatus).eq(0);
|
|
360
360
|
});
|
|
361
361
|
|
|
362
|
+
it('onDidStartTaskProcess is fired when a terminal-process task is created', async function (): Promise<void> {
|
|
363
|
+
const command = isWindows ? commandShortRunningWindows : (isOSX ? commandShortRunningOsx : commandShortRunning);
|
|
364
|
+
let startEvent: TaskInfo | undefined;
|
|
365
|
+
const toDispose = taskWatcher.onDidStartTaskProcess(event => { startEvent = event; });
|
|
366
|
+
const taskInfo = await taskServer.run(createProcessTaskConfig('shell', command, undefined), wsRoot);
|
|
367
|
+
toDispose.dispose();
|
|
368
|
+
|
|
369
|
+
if (startEvent === undefined) {
|
|
370
|
+
throw new Error('onDidStartTaskProcess was not fired');
|
|
371
|
+
}
|
|
372
|
+
expect(startEvent.taskId).equals(taskInfo.taskId);
|
|
373
|
+
expect(startEvent.processId).to.be.a('number');
|
|
374
|
+
await checkSuccessfulProcessExit(taskInfo, taskWatcher);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('onDidStartTaskProcess is fired when a raw-process task is created', async function (): Promise<void> {
|
|
378
|
+
const command = isWindows ? commandShortRunningWindows : (isOSX ? commandShortRunningOsx : commandShortRunning);
|
|
379
|
+
const executable = FileUri.fsPath(wsRootUri.resolve(command));
|
|
380
|
+
let startEvent: TaskInfo | undefined;
|
|
381
|
+
const toDispose = taskWatcher.onDidStartTaskProcess(event => { startEvent = event; });
|
|
382
|
+
const taskInfo = await taskServer.run(createProcessTaskConfig('process', executable, []), wsRoot);
|
|
383
|
+
toDispose.dispose();
|
|
384
|
+
|
|
385
|
+
if (startEvent === undefined) {
|
|
386
|
+
throw new Error('onDidStartTaskProcess was not fired');
|
|
387
|
+
}
|
|
388
|
+
expect(startEvent.taskId).equals(taskInfo.taskId);
|
|
389
|
+
expect(startEvent.processId).to.be.a('number');
|
|
390
|
+
await checkSuccessfulProcessExit(taskInfo, taskWatcher);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it('onDidStartTaskProcess is not fired for a non-process (custom) task', async function (): Promise<void> {
|
|
394
|
+
let processStarted = false;
|
|
395
|
+
let taskCreated = false;
|
|
396
|
+
const disposeStart = taskWatcher.onDidStartTaskProcess(() => { processStarted = true; });
|
|
397
|
+
const disposeCreated = taskWatcher.onTaskCreated(() => { taskCreated = true; });
|
|
398
|
+
const taskInfo = await taskServer.run(createCustomTaskConfig(), wsRoot);
|
|
399
|
+
disposeStart.dispose();
|
|
400
|
+
disposeCreated.dispose();
|
|
401
|
+
|
|
402
|
+
// The events are fired synchronously while `run` is awaited, so by now they have either fired or not.
|
|
403
|
+
expect(taskCreated, 'onTaskCreated was expected to fire for a custom task').to.equal(true);
|
|
404
|
+
expect(processStarted, 'onDidStartTaskProcess should not fire for a non-process task').to.equal(false);
|
|
405
|
+
await taskServer.kill(taskInfo.taskId);
|
|
406
|
+
});
|
|
407
|
+
|
|
362
408
|
});
|
|
363
409
|
|
|
364
410
|
function createTaskConfig(taskType: string, command: string, args: string[]): TaskConfiguration {
|
|
@@ -397,6 +443,15 @@ function createProcessTaskConfig2(processType: ProcessType, command: string, arg
|
|
|
397
443
|
};
|
|
398
444
|
}
|
|
399
445
|
|
|
446
|
+
function createCustomTaskConfig(): TaskConfiguration {
|
|
447
|
+
return {
|
|
448
|
+
label: 'test custom task',
|
|
449
|
+
type: 'customExecution',
|
|
450
|
+
_source: '/source/folder',
|
|
451
|
+
_scope: '/source/folder'
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
|
|
400
455
|
function createTaskConfigTaskLongRunning(processType: ProcessType): TaskConfiguration {
|
|
401
456
|
return <ProcessTaskConfiguration>{
|
|
402
457
|
label: '[Task] long running test task (~300s)',
|
package/src/node/task-server.ts
CHANGED
|
@@ -163,7 +163,7 @@ export class TaskServerImpl implements TaskServer, Disposable {
|
|
|
163
163
|
this.toDispose.get(task.id)!.push(task);
|
|
164
164
|
|
|
165
165
|
const taskInfo = await task.getRuntimeInfo();
|
|
166
|
-
this.fireTaskCreatedEvent(taskInfo);
|
|
166
|
+
this.fireTaskCreatedEvent(taskInfo, task);
|
|
167
167
|
return taskInfo;
|
|
168
168
|
}
|
|
169
169
|
|