Skip to content

Commit e2bd282

Browse files
authored
Merge pull request microsoft#22254 from JoshuaKGoldberg/pretty-watch-error-summaries
Added an errors summary for --pretty --watch results
2 parents ae714c5 + 0dbebec commit e2bd282

3 files changed

Lines changed: 78 additions & 16 deletions

File tree

src/compiler/diagnosticMessages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3516,6 +3516,14 @@
35163516
"category": "Error",
35173517
"code": 6192
35183518
},
3519+
"Found 1 error.": {
3520+
"category": "Message",
3521+
"code": 6193
3522+
},
3523+
"Found {0} errors.": {
3524+
"category": "Message",
3525+
"code": 6194
3526+
},
35193527
"Variable '{0}' implicitly has an '{1}' type.": {
35203528
"category": "Error",
35213529
"code": 7005

src/compiler/watch.ts

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,19 @@ namespace ts {
3131
};
3232
}
3333

34+
/** @internal */
35+
export const nonClearingMessageCodes: number[] = [
36+
Diagnostics.Compilation_complete_Watching_for_file_changes.code,
37+
Diagnostics.Found_1_error.code,
38+
Diagnostics.Found_0_errors.code
39+
];
40+
3441
function clearScreenIfNotWatchingForFileChanges(system: System, diagnostic: Diagnostic, options: CompilerOptions) {
3542
if (system.clearScreen &&
3643
!options.preserveWatchOutput &&
37-
diagnostic.code !== Diagnostics.Compilation_complete_Watching_for_file_changes.code &&
3844
!options.extendedDiagnostics &&
39-
!options.diagnostics) {
45+
!options.diagnostics &&
46+
!contains(nonClearingMessageCodes, diagnostic.code)) {
4047
system.clearScreen();
4148
}
4249
}
@@ -115,10 +122,12 @@ namespace ts {
115122
emit(): EmitResult;
116123
}
117124

125+
export type ReportEmitErrorSummary = (errorCount: number) => void;
126+
118127
/**
119128
* Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options
120129
*/
121-
export function emitFilesAndReportErrors(program: ProgramToEmitFilesAndReportErrors, reportDiagnostic: DiagnosticReporter, writeFileName?: (s: string) => void) {
130+
export function emitFilesAndReportErrors(program: ProgramToEmitFilesAndReportErrors, reportDiagnostic: DiagnosticReporter, writeFileName?: (s: string) => void, reportSummary?: ReportEmitErrorSummary) {
122131
// First get and report any syntactic errors.
123132
const diagnostics = program.getConfigFileParsingDiagnostics().slice();
124133
const configFileParsingDiagnosticsLength = diagnostics.length;
@@ -159,6 +168,10 @@ namespace ts {
159168
}
160169
}
161170

171+
if (reportSummary) {
172+
reportSummary(diagnostics.filter(diagnostic => diagnostic.category === DiagnosticCategory.Error).length);
173+
}
174+
162175
if (emitSkipped && diagnostics.length > 0) {
163176
// If the emitter didn't emit anything, then pass that value along.
164177
return ExitStatus.DiagnosticsPresent_OutputsSkipped;
@@ -184,6 +197,7 @@ namespace ts {
184197
let host: DirectoryStructureHost = system;
185198
const useCaseSensitiveFileNames = () => system.useCaseSensitiveFileNames;
186199
const writeFileName = (s: string) => system.write(s + system.newLine);
200+
const onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
187201
return {
188202
useCaseSensitiveFileNames,
189203
getNewLine: () => system.newLine,
@@ -202,7 +216,7 @@ namespace ts {
202216
setTimeout: system.setTimeout ? ((callback, ms, ...args: any[]) => system.setTimeout.call(system, callback, ms, ...args)) : noop,
203217
clearTimeout: system.clearTimeout ? (timeoutId => system.clearTimeout(timeoutId)) : noop,
204218
trace: s => system.write(s),
205-
onWatchStatusChange: reportWatchStatus || createWatchStatusReporter(system),
219+
onWatchStatusChange,
206220
createDirectory: path => system.createDirectory(path),
207221
writeFile: (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark),
208222
onCachedDirectoryStructureHostCreate: cacheHost => host = cacheHost || system,
@@ -216,7 +230,19 @@ namespace ts {
216230
}
217231

218232
function emitFilesAndReportErrorUsingBuilder(builderProgram: BuilderProgram) {
219-
emitFilesAndReportErrors(builderProgram, reportDiagnostic, writeFileName);
233+
const compilerOptions = builderProgram.getCompilerOptions();
234+
const newLine = getNewLineCharacter(compilerOptions, () => system.newLine);
235+
236+
const reportSummary = (errorCount: number) => {
237+
if (errorCount === 1) {
238+
onWatchStatusChange(createCompilerDiagnostic(Diagnostics.Found_1_error, errorCount), newLine, compilerOptions);
239+
}
240+
else {
241+
onWatchStatusChange(createCompilerDiagnostic(Diagnostics.Found_0_errors, errorCount, errorCount), newLine, compilerOptions);
242+
}
243+
};
244+
245+
emitFilesAndReportErrors(builderProgram, reportDiagnostic, writeFileName, reportSummary);
220246
}
221247
}
222248

src/harness/unittests/tscWatchMode.ts

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ namespace ts.tscWatch {
7676
function checkOutputErrors(
7777
host: WatchedSystem,
7878
logsBeforeWatchDiagnostic: string[] | undefined,
79-
preErrorsWatchDiagnostic: DiagnosticMessage,
79+
preErrorsWatchDiagnostic: Diagnostic,
8080
logsBeforeErrors: string[] | undefined,
8181
errors: ReadonlyArray<Diagnostic>,
8282
disableConsoleClears?: boolean | undefined,
83-
...postErrorsWatchDiagnostics: DiagnosticMessage[]
83+
...postErrorsWatchDiagnostics: Diagnostic[]
8484
) {
8585
let screenClears = 0;
8686
const outputs = host.getOutput();
@@ -109,9 +109,9 @@ namespace ts.tscWatch {
109109
index++;
110110
}
111111

112-
function assertWatchDiagnostic(diagnosticMessage: DiagnosticMessage) {
113-
const expected = getWatchDiagnosticWithoutDate(diagnosticMessage);
114-
if (!disableConsoleClears && diagnosticMessage.code !== Diagnostics.Compilation_complete_Watching_for_file_changes.code) {
112+
function assertWatchDiagnostic(diagnostic: Diagnostic) {
113+
const expected = getWatchDiagnosticWithoutDate(diagnostic);
114+
if (!disableConsoleClears && !contains(nonClearingMessageCodes, diagnostic.code)) {
115115
assert.equal(host.screenClears[screenClears], index, `Expected screen clear at this diagnostic: ${expected}`);
116116
screenClears++;
117117
}
@@ -120,24 +120,52 @@ namespace ts.tscWatch {
120120
}
121121

122122
function getOutputAtFailedMessage(caption: string, expectedOutput: string) {
123-
return `Expected ${caption}: ${expectedOutput} at ${index} in ${JSON.stringify(outputs)}`;
123+
return `Expected ${caption}: ${JSON.stringify(expectedOutput)} at ${index} in ${JSON.stringify(outputs)}`;
124124
}
125125

126-
function getWatchDiagnosticWithoutDate(diagnosticMessage: DiagnosticMessage) {
127-
return ` - ${flattenDiagnosticMessageText(getLocaleSpecificMessage(diagnosticMessage), host.newLine)}${host.newLine + host.newLine + host.newLine}`;
126+
function getWatchDiagnosticWithoutDate(diagnostic: Diagnostic) {
127+
return ` - ${flattenDiagnosticMessageText(diagnostic.messageText, host.newLine)}${host.newLine + host.newLine + host.newLine}`;
128128
}
129129
}
130130

131+
function createErrorsFoundCompilerDiagnostic(errors: ReadonlyArray<Diagnostic>) {
132+
return errors.length === 1
133+
? createCompilerDiagnostic(Diagnostics.Found_1_error)
134+
: createCompilerDiagnostic(Diagnostics.Found_0_errors, errors.length);
135+
}
136+
131137
function checkOutputErrorsInitial(host: WatchedSystem, errors: ReadonlyArray<Diagnostic>, disableConsoleClears?: boolean, logsBeforeErrors?: string[]) {
132-
checkOutputErrors(host, /*logsBeforeWatchDiagnostic*/ undefined, Diagnostics.Starting_compilation_in_watch_mode, logsBeforeErrors, errors, disableConsoleClears, Diagnostics.Compilation_complete_Watching_for_file_changes);
138+
checkOutputErrors(
139+
host,
140+
/*logsBeforeWatchDiagnostic*/ undefined,
141+
createCompilerDiagnostic(Diagnostics.Starting_compilation_in_watch_mode),
142+
logsBeforeErrors,
143+
errors,
144+
disableConsoleClears,
145+
createErrorsFoundCompilerDiagnostic(errors),
146+
createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes));
133147
}
134148

135149
function checkOutputErrorsIncremental(host: WatchedSystem, errors: ReadonlyArray<Diagnostic>, disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) {
136-
checkOutputErrors(host, logsBeforeWatchDiagnostic, Diagnostics.File_change_detected_Starting_incremental_compilation, logsBeforeErrors, errors, disableConsoleClears, Diagnostics.Compilation_complete_Watching_for_file_changes);
150+
checkOutputErrors(
151+
host,
152+
logsBeforeWatchDiagnostic,
153+
createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation),
154+
logsBeforeErrors,
155+
errors,
156+
disableConsoleClears,
157+
createErrorsFoundCompilerDiagnostic(errors),
158+
createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes));
137159
}
138160

139161
function checkOutputErrorsIncrementalWithExit(host: WatchedSystem, errors: ReadonlyArray<Diagnostic>, expectedExitCode: ExitStatus, disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) {
140-
checkOutputErrors(host, logsBeforeWatchDiagnostic, Diagnostics.File_change_detected_Starting_incremental_compilation, logsBeforeErrors, errors, disableConsoleClears);
162+
checkOutputErrors(
163+
host,
164+
logsBeforeWatchDiagnostic,
165+
createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation),
166+
logsBeforeErrors,
167+
errors,
168+
disableConsoleClears);
141169
assert.equal(host.exitCode, expectedExitCode);
142170
}
143171

0 commit comments

Comments
 (0)