@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.
Files changed (30) hide show
  1. package/lib/browser/task-configurations.d.ts +2 -0
  2. package/lib/browser/task-configurations.d.ts.map +1 -1
  3. package/lib/browser/task-configurations.js +9 -3
  4. package/lib/browser/task-configurations.js.map +1 -1
  5. package/lib/browser/task-problem-matcher-registry.d.ts +2 -0
  6. package/lib/browser/task-problem-matcher-registry.d.ts.map +1 -1
  7. package/lib/browser/task-problem-matcher-registry.js +7 -1
  8. package/lib/browser/task-problem-matcher-registry.js.map +1 -1
  9. package/lib/browser/task-problem-pattern-registry.d.ts +2 -0
  10. package/lib/browser/task-problem-pattern-registry.d.ts.map +1 -1
  11. package/lib/browser/task-problem-pattern-registry.js +7 -1
  12. package/lib/browser/task-problem-pattern-registry.js.map +1 -1
  13. package/lib/browser/task-service.js +15 -14
  14. package/lib/browser/task-service.js.map +1 -1
  15. package/lib/browser/task-terminal-widget-manager.d.ts +1 -7
  16. package/lib/browser/task-terminal-widget-manager.d.ts.map +1 -1
  17. package/lib/browser/task-terminal-widget-manager.js +6 -34
  18. package/lib/browser/task-terminal-widget-manager.js.map +1 -1
  19. package/lib/node/task-server.js +1 -1
  20. package/lib/node/task-server.js.map +1 -1
  21. package/lib/node/task-server.slow-spec.js +49 -1
  22. package/lib/node/task-server.slow-spec.js.map +1 -1
  23. package/package.json +13 -14
  24. package/src/browser/task-configurations.ts +8 -4
  25. package/src/browser/task-problem-matcher-registry.ts +6 -2
  26. package/src/browser/task-problem-pattern-registry.ts +7 -2
  27. package/src/browser/task-service.ts +15 -15
  28. package/src/browser/task-terminal-widget-manager.ts +7 -30
  29. package/src/node/task-server.slow-spec.ts +56 -1
  30. 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
- console.error('Invalid TaskExitedEvent received, neither code nor signal is set.');
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
- console.error('Error at launching task', error);
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
- console.error(`Error at launching task '${task.label}'`, error);
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
- console.error(`Error at launching task '${task.label}'`, error);
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
- console.debug('entering runTask');
762
+ this.logger.debug('entering runTask');
763
763
  const releaseLock = await this.taskStartingLock.acquire();
764
- console.debug('got lock');
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
- console.debug(`running task ${JSON.stringify(task)}, already running = ${!!matchedRunningTaskInfo}`);
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
- console.debug('released lock');
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
- console.debug('task about to start');
808
+ this.logger.debug('task about to start');
809
809
  const taskInfo = await this.doRunTask(task, option);
810
810
  releaseLock();
811
- console.debug('release lock 2');
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
- console.log(error.message);
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: new Date().toString() });
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: new Date().toString(),
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 { ApplicationShell, WidgetManager, WidgetOpenerOptions } from '@theia/core/lib/browser';
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
- const isTreeMode = this.preferences['terminal.grouping.mode'] === 'tree';
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
- if (TaskTerminalWidgetOpenerOptions.echoExecutedCommand(openerOptions) &&
176
- taskInfo && ProcessTaskInfo.is(taskInfo) && taskInfo.command && taskInfo.command.length > 0
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.writeLine('\x1b]133;prompt_started\x07');
156
+ widget.write('\x1b]133;prompt_started\x07');
180
157
  }
181
- widget.writeLine('\x1b[1m> ' + nls.localizeByDefault('Executing task: {0}', taskInfo.command) + ' <\x1b[0m\n');
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
- channel.onClose(() => reject(new Error('Channel has been closed')));
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)',
@@ -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