Skip to content

Commit e0d067b

Browse files
author
Josh Goldberg
committed
Added an errors summary for --pretty --watch results
Reports a "Found X error(s) across Y file(s)." message on each recompile if in both pretty and watch modes. This commit intentionally doesn't include tests as I have a few questions about implementation details. Will ask in PR first.
1 parent b31aa4e commit e0d067b

3 files changed

Lines changed: 78 additions & 9 deletions

File tree

src/compiler/diagnosticMessages.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3472,6 +3472,18 @@
34723472
"category": "Message",
34733473
"code": 6190
34743474
},
3475+
"Found 1 error in 1 file.": {
3476+
"category": "Message",
3477+
"code": 6191
3478+
},
3479+
"Found {0} errors in 1 file.": {
3480+
"category": "Message",
3481+
"code": 6192
3482+
},
3483+
"Found {0} errors in {1} files.": {
3484+
"category": "Message",
3485+
"code": 6193
3486+
},
34753487
"Variable '{0}' implicitly has an '{1}' type.": {
34763488
"category": "Error",
34773489
"code": 7005

src/compiler/tsc.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ namespace ts {
144144
enableStatistics(compilerOptions);
145145

146146
const program = createProgram(rootFileNames, compilerOptions, compilerHost);
147-
const exitStatus = emitFilesAndReportErrors(program, reportDiagnostic, s => sys.write(s + sys.newLine));
147+
const diagnosticsAndEmit = getProgramDiagnosticsAndEmit(program);
148+
const exitStatus = reportDiagnosticErrors(program, diagnosticsAndEmit, reportDiagnostic, s => sys.write(s + sys.newLine));
148149
reportStatistics(program);
149150
return sys.exit(exitStatus);
150151
}

src/compiler/watch.ts

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,18 @@ namespace ts {
3131
};
3232
}
3333

34+
const nonClearingMessageCodes: number[] = [
35+
Diagnostics.Compilation_complete_Watching_for_file_changes.code,
36+
Diagnostics.Found_1_error_in_1_file.code,
37+
Diagnostics.Found_0_errors_in_1_file.code,
38+
Diagnostics.Found_0_errors_in_1_files.code,
39+
];
40+
3441
function clearScreenIfNotWatchingForFileChanges(system: System, diagnostic: Diagnostic, options: CompilerOptions) {
3542
if (system.clearScreen &&
36-
diagnostic.code !== Diagnostics.Compilation_complete_Watching_for_file_changes.code &&
3743
!options.extendedDiagnostics &&
38-
!options.diagnostics) {
44+
!options.diagnostics &&
45+
!contains(nonClearingMessageCodes, diagnostic.code)) {
3946
system.clearScreen();
4047
}
4148
}
@@ -120,10 +127,15 @@ namespace ts {
120127
emit(): EmitResult;
121128
}
122129

123-
/**
124-
* Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options
125-
*/
126-
export function emitFilesAndReportErrors(program: ProgramToEmitFilesAndReportErrors, reportDiagnostic: DiagnosticReporter, writeFileName?: (s: string) => void) {
130+
/** @internal */
131+
export interface ProgramDiagnosticsAndEmit {
132+
diagnostics: Diagnostic[];
133+
emittedFiles: string[];
134+
emitSkipped: boolean;
135+
}
136+
137+
/** @internal */
138+
export function getProgramDiagnosticsAndEmit(program: ProgramToEmitFilesAndReportErrors): ProgramDiagnosticsAndEmit {
127139
// First get and report any syntactic errors.
128140
const diagnostics = program.getSyntacticDiagnostics().slice();
129141
let reportSemanticDiagnostics = false;
@@ -147,6 +159,15 @@ namespace ts {
147159
addRange(diagnostics, program.getSemanticDiagnostics());
148160
}
149161

162+
return { diagnostics, emittedFiles, emitSkipped };
163+
}
164+
165+
/**
166+
* Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options
167+
*/
168+
export function reportDiagnosticErrors(program: ProgramToEmitFilesAndReportErrors, diagnosticsAndEmit: ProgramDiagnosticsAndEmit, reportDiagnostic: DiagnosticReporter, writeFileName?: (s: string) => void) {
169+
const { diagnostics, emittedFiles, emitSkipped } = diagnosticsAndEmit;
170+
150171
sortAndDeduplicateDiagnostics(diagnostics).forEach(reportDiagnostic);
151172
if (writeFileName) {
152173
const currentDir = program.getCurrentDirectory();
@@ -174,6 +195,34 @@ namespace ts {
174195
return ExitStatus.Success;
175196
}
176197

198+
function summarizeDiagnosticsAcrossFiles(diagnostics: Diagnostic[], reporter: WatchStatusReporter, newLine: string, compilerOptions: CompilerOptions): void {
199+
if (diagnostics.length === 1) {
200+
reporter(createCompilerDiagnostic(Diagnostics.Found_1_error_in_1_file), newLine, compilerOptions);
201+
return;
202+
}
203+
204+
const uniqueFileNamesCount = countUniqueDiagnosticFileNames(diagnostics);
205+
206+
if (uniqueFileNamesCount === 1) {
207+
reporter(createCompilerDiagnostic(Diagnostics.Found_0_errors_in_1_file, diagnostics.length), newLine, compilerOptions);
208+
}
209+
else if (uniqueFileNamesCount !== 0) {
210+
reporter(createCompilerDiagnostic(Diagnostics.Found_0_errors_in_1_files, diagnostics.length, uniqueFileNamesCount), newLine, compilerOptions);
211+
}
212+
}
213+
214+
function countUniqueDiagnosticFileNames(diagnostics: Diagnostic[]): number {
215+
const fileNames = createMap<boolean>();
216+
217+
for (const diagnostic of diagnostics) {
218+
if (diagnostic.file) {
219+
fileNames.set(diagnostic.file.fileName, true);
220+
}
221+
}
222+
223+
return fileNames.size;
224+
}
225+
177226
const noopFileWatcher: FileWatcher = { close: noop };
178227

179228
/**
@@ -187,6 +236,7 @@ namespace ts {
187236
let host: DirectoryStructureHost = system;
188237
const useCaseSensitiveFileNames = () => system.useCaseSensitiveFileNames;
189238
const writeFileName = (s: string) => system.write(s + system.newLine);
239+
const onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
190240
return {
191241
useCaseSensitiveFileNames,
192242
getNewLine: () => system.newLine,
@@ -205,7 +255,7 @@ namespace ts {
205255
setTimeout: system.setTimeout ? ((callback, ms, ...args: any[]) => system.setTimeout.call(system, callback, ms, ...args)) : noop,
206256
clearTimeout: system.clearTimeout ? (timeoutId => system.clearTimeout(timeoutId)) : noop,
207257
trace: s => system.write(s),
208-
onWatchStatusChange: reportWatchStatus || createWatchStatusReporter(system),
258+
onWatchStatusChange,
209259
createDirectory: path => system.createDirectory(path),
210260
writeFile: (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark),
211261
onCachedDirectoryStructureHostCreate: cacheHost => host = cacheHost || system,
@@ -219,7 +269,13 @@ namespace ts {
219269
}
220270

221271
function emitFilesAndReportErrorUsingBuilder(builderProgram: BuilderProgram) {
222-
emitFilesAndReportErrors(builderProgram, reportDiagnostic, writeFileName);
272+
const diagnosticsAndEmit = getProgramDiagnosticsAndEmit(builderProgram);
273+
reportDiagnosticErrors(builderProgram, diagnosticsAndEmit, reportDiagnostic, writeFileName);
274+
275+
const compilerOptions = builderProgram.getCompilerOptions();
276+
if (compilerOptions.pretty) {
277+
summarizeDiagnosticsAcrossFiles(diagnosticsAndEmit.diagnostics, onWatchStatusChange, system.newLine, compilerOptions);
278+
}
223279
}
224280
}
225281

0 commit comments

Comments
 (0)