Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/lib/reporter.ts
3520 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 es from 'event-stream';
7
import fancyLog from 'fancy-log';
8
import ansiColors from 'ansi-colors';
9
import fs from 'fs';
10
import path from 'path';
11
12
class ErrorLog {
13
constructor(public id: string) {
14
}
15
allErrors: string[][] = [];
16
startTime: number | null = null;
17
count = 0;
18
19
onStart(): void {
20
if (this.count++ > 0) {
21
return;
22
}
23
24
this.startTime = new Date().getTime();
25
fancyLog(`Starting ${ansiColors.green('compilation')}${this.id ? ansiColors.blue(` ${this.id}`) : ''}...`);
26
}
27
28
onEnd(): void {
29
if (--this.count > 0) {
30
return;
31
}
32
33
this.log();
34
}
35
36
log(): void {
37
const errors = this.allErrors.flat();
38
const seen = new Set<string>();
39
40
errors.map(err => {
41
if (!seen.has(err)) {
42
seen.add(err);
43
fancyLog(`${ansiColors.red('Error')}: ${err}`);
44
}
45
});
46
47
fancyLog(`Finished ${ansiColors.green('compilation')}${this.id ? ansiColors.blue(` ${this.id}`) : ''} with ${errors.length} errors after ${ansiColors.magenta((new Date().getTime() - this.startTime!) + ' ms')}`);
48
49
const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/s;
50
const messages = errors
51
.map(err => regex.exec(err))
52
.filter(match => !!match)
53
.map(x => x as string[])
54
.map(([, path, line, column, message]) => ({ path, line: parseInt(line), column: parseInt(column), message }));
55
56
try {
57
const logFileName = 'log' + (this.id ? `_${this.id}` : '');
58
fs.writeFileSync(path.join(buildLogFolder, logFileName), JSON.stringify(messages));
59
} catch (err) {
60
//noop
61
}
62
}
63
64
}
65
66
const errorLogsById = new Map<string, ErrorLog>();
67
function getErrorLog(id: string = '') {
68
let errorLog = errorLogsById.get(id);
69
if (!errorLog) {
70
errorLog = new ErrorLog(id);
71
errorLogsById.set(id, errorLog);
72
}
73
return errorLog;
74
}
75
76
const buildLogFolder = path.join(path.dirname(path.dirname(__dirname)), '.build');
77
78
try {
79
fs.mkdirSync(buildLogFolder);
80
} catch (err) {
81
// ignore
82
}
83
84
export interface IReporter {
85
(err: string): void;
86
hasErrors(): boolean;
87
end(emitError: boolean): NodeJS.ReadWriteStream;
88
}
89
90
export function createReporter(id?: string): IReporter {
91
const errorLog = getErrorLog(id);
92
93
const errors: string[] = [];
94
errorLog.allErrors.push(errors);
95
96
const result = (err: string) => errors.push(err);
97
98
result.hasErrors = () => errors.length > 0;
99
100
result.end = (emitError: boolean): NodeJS.ReadWriteStream => {
101
errors.length = 0;
102
errorLog.onStart();
103
104
return es.through(undefined, function () {
105
errorLog.onEnd();
106
107
if (emitError && errors.length > 0) {
108
if (!(errors as any).__logged__) {
109
errorLog.log();
110
}
111
112
(errors as any).__logged__ = true;
113
114
const err = new Error(`Found ${errors.length} errors`);
115
(err as any).__reporter__ = true;
116
this.emit('error', err);
117
} else {
118
this.emit('end');
119
}
120
});
121
};
122
123
return result;
124
}
125
126