Skip to content

Commit 6d620e0

Browse files
committed
Show error count, fix #138
1 parent da9057b commit 6d620e0

File tree

4 files changed

+85
-18
lines changed

4 files changed

+85
-18
lines changed

lib/compiler.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Output, OutputFileKind } from './output';
88
import { Host } from './host';
99
import { Project } from './project';
1010
import { Filter } from './filter';
11+
import { CompilationResult, emptyCompilationResult } from './reporter';
1112
import * as utils from './utils';
1213

1314
export interface ICompiler {
@@ -38,7 +39,7 @@ export class ProjectCompiler implements ICompiler {
3839

3940
inputDone() {
4041
if (!this.project.input.firstSourceFile) {
41-
this.project.output.finish();
42+
this.project.output.finish(emptyCompilationResult());
4243
return;
4344
}
4445

@@ -58,6 +59,8 @@ export class ProjectCompiler implements ICompiler {
5859
this.project.output.write(file.fileName + '.d.ts', file.content[OutputFileKind.Definitions]);
5960
}
6061
}
62+
63+
this.project.output.finish(old.results);
6164

6265
return;
6366
}
@@ -91,7 +94,7 @@ export class ProjectCompiler implements ICompiler {
9194
// Creating a program to compile the sources
9295
this.program = this.project.typescript.createProgram(rootFilenames, this.project.options, this.host);
9396

94-
const errors = tsApi.getDiagnosticsAndEmit(this.program);
97+
const [errors, result] = tsApi.getDiagnosticsAndEmit(this.program);
9598

9699
for (let i = 0; i < errors.length; i++) {
97100
this.project.output.diagnostic(errors[i]);
@@ -103,7 +106,7 @@ export class ProjectCompiler implements ICompiler {
103106
this.project.output.write(fileName, this.host.output[fileName]);
104107
}
105108

106-
this.project.output.finish();
109+
this.project.output.finish(result);
107110
}
108111

109112
private _commonBaseDiff: [number, string];

lib/output.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export class Output {
4242
project: project.Project;
4343
files: utils.Map<OutputFile> = {};
4444
errors: reporter.TypeScriptError[] = [];
45+
results: reporter.CompilationResult;
4546
streamJs: stream.Readable;
4647
streamDts: stream.Readable;
4748

@@ -196,7 +197,7 @@ export class Output {
196197
}
197198
}
198199

199-
finish() {
200+
finish(results: reporter.CompilationResult) {
200201
if (this.project.sortOutput) {
201202
let sortedEmit = (fileName: string) => {
202203
let file = this.files[fileName];
@@ -215,6 +216,9 @@ export class Output {
215216
sortedEmit(fileName);
216217
}
217218
}
219+
220+
this.results = results;
221+
if (this.project.reporter.finish) this.project.reporter.finish(results);
218222

219223
this.streamJs.push(null);
220224
this.streamDts.push(null);

lib/reporter.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,48 @@ export interface TypeScriptError extends Error {
2323
character: number;
2424
};
2525
}
26+
export interface CompilationResult {
27+
syntaxErrors: number;
28+
globalErrors: number;
29+
semanticErrors: number;
30+
emitErrors: number;
31+
32+
emitSkipped: boolean;
33+
}
34+
export function emptyCompilationResult() {
35+
return {
36+
syntaxErrors: 0,
37+
globalErrors: 0,
38+
semanticErrors: 0,
39+
emitErrors: 0,
40+
emitSkipped: false
41+
}
42+
}
2643

2744
export interface Reporter {
2845
error?: (error: TypeScriptError, typescript: typeof ts) => void;
46+
finish?: (results: CompilationResult) => void;
47+
}
48+
49+
function defaultFinishHandler(results: CompilationResult) {
50+
let hasError = false;
51+
const showErrorCount = (count: number, type: string) => {
52+
if (count === 0) return;
53+
54+
gutil.log('TypeScript:', gutil.colors.magenta(count.toString()), type + ' ' + (count === 1 ? 'error' : 'errors'));
55+
hasError = true;
56+
};
57+
58+
showErrorCount(results.syntaxErrors, 'syntax');
59+
showErrorCount(results.globalErrors, 'global');
60+
showErrorCount(results.semanticErrors, 'semantic');
61+
showErrorCount(results.emitErrors, 'emit');
62+
63+
if (results.emitSkipped) {
64+
gutil.log('TypeScript: emit', gutil.colors.red('failed'));
65+
} else if (hasError) {
66+
gutil.log('TypeScript: emit', gutil.colors.cyan('succeeded'), '(with errors)');
67+
}
2968
}
3069

3170
export function nullReporter(): Reporter {
@@ -35,7 +74,8 @@ export function defaultReporter(): Reporter {
3574
return {
3675
error: (error: TypeScriptError) => {
3776
console.error(error.message);
38-
}
77+
},
78+
finish: defaultFinishHandler
3979
};
4080
}
4181

@@ -63,7 +103,8 @@ export function longReporter(): Reporter {
63103
} else {
64104
console.error(error.message);
65105
}
66-
}
106+
},
107+
finish: defaultFinishHandler
67108
}
68109
}
69110
export function fullReporter(fullFilename: boolean = false): Reporter {
@@ -95,6 +136,7 @@ export function fullReporter(fullFilename: boolean = false): Reporter {
95136
);
96137
}
97138
}
98-
}
139+
},
140+
finish: defaultFinishHandler
99141
}
100142
}

lib/tsapi.ts

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as ts from 'typescript';
2+
import { CompilationResult, emptyCompilationResult } from './reporter';
23

34
export interface TypeScript14 {
45
createSourceFile(filename: string, content: string, target: ts.ScriptTarget, version: string);
@@ -22,12 +23,12 @@ export interface Program15 {
2223
getGlobalDiagnostics(): ts.Diagnostic[];
2324
getSemanticDiagnostics(): ts.Diagnostic[];
2425
getDeclarationDiagnostics(): ts.Diagnostic[];
25-
emit(): { diagnostics: ts.Diagnostic[]; };
26+
emit(): { diagnostics: ts.Diagnostic[]; emitSkipped: boolean; };
2627
}
2728

2829
export interface TypeChecker14 {
2930
getDiagnostics(sourceFile?: ts.SourceFile): ts.Diagnostic[];
30-
emitFiles(): { diagnostics: ts.Diagnostic[] };
31+
emitFiles(): { diagnostics: ts.Diagnostic[]; };
3132
}
3233
export interface DiagnosticMessageChain15 {
3334
messageText: string;
@@ -54,9 +55,13 @@ export function getFileName(thing: { filename: string} | { fileName: string }):
5455
if ((<any> thing).filename) return (<any> thing).filename; // TS 1.4
5556
return (<any> thing).fileName; // TS 1.5
5657
}
57-
export function getDiagnosticsAndEmit(program: Program14 | Program15): ts.Diagnostic[] {
58+
export function getDiagnosticsAndEmit(program: Program14 | Program15): [ts.Diagnostic[], CompilationResult] {
59+
let result = emptyCompilationResult();
60+
5861
if ((<Program14> program).getDiagnostics) { // TS 1.4
5962
let errors = (<Program14> program).getDiagnostics();
63+
64+
result.syntaxErrors = errors.length;
6065

6166
if (!errors.length) {
6267
// If there are no syntax errors, check types
@@ -67,21 +72,34 @@ export function getDiagnosticsAndEmit(program: Program14 | Program15): ts.Diagno
6772
const emitErrors = checker.emitFiles().diagnostics;
6873

6974
errors = semanticErrors.concat(emitErrors);
75+
result.semanticErrors = errors.length;
76+
} else {
77+
result.emitSkipped = true;
7078
}
7179

72-
return errors;
80+
return [errors, result];
7381
} else { // TS 1.5
7482
let errors = (<Program15> program).getSyntacticDiagnostics();
75-
if (errors.length === 0) errors = (<Program15> program).getGlobalDiagnostics();
76-
77-
// Remove error: "File '...' is not under 'rootDir' '...'. 'rootDir' is expected to contain all source files."
78-
// This is handled by ICompiler#correctSourceMap, so this error can be muted.
79-
errors = errors.filter((item) => item.code !== 6059);
83+
result.syntaxErrors = errors.length;
84+
if (errors.length === 0) {
85+
errors = (<Program15> program).getGlobalDiagnostics();
86+
87+
// Remove error: "File '...' is not under 'rootDir' '...'. 'rootDir' is expected to contain all source files."
88+
// This is handled by ICompiler#correctSourceMap, so this error can be muted.
89+
errors = errors.filter((item) => item.code !== 6059);
90+
91+
result.globalErrors = errors.length;
92+
}
8093

81-
if (errors.length === 0) errors = (<Program15> program).getSemanticDiagnostics();
94+
if (errors.length === 0) {
95+
errors = (<Program15> program).getSemanticDiagnostics();
96+
result.semanticErrors = errors.length;
97+
}
8298

8399
const emitOutput = (<Program15> program).emit();
84-
return errors.concat(emitOutput.diagnostics);
100+
result.emitErrors = emitOutput.diagnostics.length;
101+
result.emitSkipped = emitOutput.emitSkipped;
102+
return [errors.concat(emitOutput.diagnostics), result];
85103
}
86104
}
87105
export function getLineAndCharacterOfPosition(typescript: typeof ts, file: TSFile14 | TSFile15, position: number) {

0 commit comments

Comments
 (0)