Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/lib/tsgo.ts
5232 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as cp from 'child_process';
7
import es from 'event-stream';
8
import * as path from 'path';
9
import { createReporter } from './reporter.ts';
10
11
const root = path.dirname(path.dirname(import.meta.dirname));
12
const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx';
13
const ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
14
15
export function spawnTsgo(projectPath: string, onComplete?: () => Promise<void> | void): Promise<void> {
16
const reporter = createReporter('extensions');
17
let report: NodeJS.ReadWriteStream | undefined;
18
19
const beginReport = (emitError: boolean) => {
20
if (report) {
21
report.end();
22
}
23
report = reporter.end(emitError);
24
};
25
26
const endReport = () => {
27
if (!report) {
28
return;
29
}
30
report.end();
31
report = undefined;
32
};
33
34
const args = ['tsgo', '--project', projectPath, '--pretty', 'false', '--sourceMap', '--inlineSources'];
35
36
beginReport(false);
37
38
const child = cp.spawn(npx, args, {
39
cwd: root,
40
stdio: ['ignore', 'pipe', 'pipe'],
41
shell: true
42
});
43
44
let buffer = '';
45
const handleLine = (line: string) => {
46
const trimmed = line.replace(ansiRegex, '').trim();
47
if (!trimmed) {
48
return;
49
}
50
if (/Starting compilation|File change detected/i.test(trimmed)) {
51
beginReport(false);
52
return;
53
}
54
if (/Compilation complete/i.test(trimmed)) {
55
endReport();
56
return;
57
}
58
59
const match = /(.*\(\d+,\d+\): )(.*: )(.*)/.exec(trimmed);
60
61
if (match) {
62
const fullpath = path.isAbsolute(match[1]) ? match[1] : path.join(root, match[1]);
63
const message = match[3];
64
reporter(fullpath + message);
65
} else {
66
reporter(trimmed);
67
}
68
};
69
70
const handleData = (data: Buffer) => {
71
buffer += data.toString('utf8');
72
const lines = buffer.split(/\r?\n/);
73
buffer = lines.pop() ?? '';
74
for (const line of lines) {
75
handleLine(line);
76
}
77
};
78
79
child.stdout?.on('data', handleData);
80
child.stderr?.on('data', handleData);
81
82
const done = new Promise<void>((resolve, reject) => {
83
child.on('exit', code => {
84
if (buffer.trim()) {
85
handleLine(buffer);
86
buffer = '';
87
}
88
endReport();
89
if (code === 0) {
90
Promise.resolve(onComplete?.()).then(() => resolve(), reject);
91
return;
92
}
93
reject(new Error(`tsgo exited with code ${code ?? 'unknown'}`));
94
});
95
child.on('error', err => {
96
endReport();
97
reject(err);
98
});
99
});
100
101
return done;
102
}
103
104
export function createTsgoStream(projectPath: string, onComplete?: () => Promise<void> | void): NodeJS.ReadWriteStream {
105
const stream = es.through();
106
107
spawnTsgo(projectPath, onComplete).then(() => {
108
stream.emit('end');
109
}).catch(() => {
110
// Errors are already reported by spawnTsgo via the reporter.
111
// Don't emit 'error' on the stream as that would exit the watch process.
112
stream.emit('end');
113
});
114
115
return stream;
116
}
117
118