This repository has been archived by the owner on Dec 8, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 62
/
Copy pathoutput_channel_task_manager.ts
117 lines (111 loc) · 4.33 KB
/
output_channel_task_manager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { DiagnosticCollection, languages, window } from 'vscode';
import { Configuration } from '../configuration/Configuration';
import { ChildLogger } from '../logging/child_logger';
import { DiagnosticParser } from './diagnostic_parser';
import { normalizeDiagnosticPath, addUniqueDiagnostic } from './diagnostic_utils';
import { OutputChannelWrapper } from './output_channel_wrapper';
import { OutputChannelTaskStatusBarItem } from './output_channel_task_status_bar_item';
import { ExitCode, Task } from './task';
export class OutputChannelTaskManager {
private channel: OutputChannelWrapper;
private configuration: Configuration;
private logger: ChildLogger;
private runningTask: Task | undefined;
private diagnostics: DiagnosticCollection;
private diagnosticParser: DiagnosticParser;
private statusBarItem: OutputChannelTaskStatusBarItem;
public constructor(
configuration: Configuration,
logger: ChildLogger,
stopCommandName: string
) {
this.channel = new OutputChannelWrapper(window.createOutputChannel('Cargo'));
this.configuration = configuration;
this.logger = logger;
this.diagnostics = languages.createDiagnosticCollection('rust');
this.diagnosticParser = new DiagnosticParser();
this.statusBarItem = new OutputChannelTaskStatusBarItem(stopCommandName);
}
public async startTask(
executable: string,
preCommandArgs: string[],
command: string,
args: string[],
cwd: string,
parseOutput: boolean,
shouldShowOutputChannnel: boolean
): Promise<void> {
function prependArgsWithMessageFormatIfRequired(): void {
if (!parseOutput) {
return;
}
// Prepend arguments with arguments making cargo print output in JSON.
switch (command) {
case 'build':
case 'check':
case 'clippy':
case 'test':
case 'run':
args = ['--message-format', 'json'].concat(args);
break;
}
}
prependArgsWithMessageFormatIfRequired();
args = preCommandArgs.concat(command, ...args);
this.runningTask = new Task(
this.configuration,
this.logger.createChildLogger('Task: '),
executable,
args,
cwd
);
this.runningTask.setStarted(() => {
this.channel.clear();
this.channel.append(`Working directory: ${cwd}\n`);
this.channel.append(`Started ${executable} ${args.join(' ')}\n\n`);
this.diagnostics.clear();
});
this.runningTask.setLineReceivedInStdout(line => {
if (parseOutput && line.startsWith('{')) {
const fileDiagnostics = this.diagnosticParser.parseLine(line);
for (const fileDiagnostic of fileDiagnostics) {
fileDiagnostic.filePath = normalizeDiagnosticPath(fileDiagnostic.filePath, cwd);
addUniqueDiagnostic(fileDiagnostic, this.diagnostics);
}
} else {
this.channel.append(`${line}\n`);
}
});
this.runningTask.setLineReceivedInStderr(line => {
this.channel.append(`${line}\n`);
});
if (shouldShowOutputChannnel) {
this.channel.show();
}
this.statusBarItem.show();
let exitCode: ExitCode;
try {
exitCode = await this.runningTask.execute();
} catch (error) {
this.statusBarItem.hide();
this.runningTask = undefined;
// No error means the task has been interrupted
if (error && error.message === 'ENOENT') {
const message = 'The "cargo" command is not available. Make sure it is installed.';
window.showInformationMessage(message);
}
return;
}
this.statusBarItem.hide();
this.runningTask = undefined;
this.channel.append(`\nCompleted with code ${exitCode}\n`);
}
public hasRunningTask(): boolean {
return this.runningTask !== undefined;
}
public async stopRunningTask(): Promise<void> {
if (this.runningTask !== undefined) {
await this.runningTask.kill();
}
}
}