feat(ivy): output diagnostics for many errors in ngtsc (#25647)

This commit takes the first steps towards ngtsc producing real
TypeScript diagnostics instead of simply throwing errors when
encountering incorrect code.

A new class is introduced, FatalDiagnosticError, which can be thrown by
handlers whenever a condition in the code is encountered which by
necessity prevents the class from being compiled. This error type is
convertable to a ts.Diagnostic which represents the type and source of
the error.

Error codes are introduced for Angular errors, and are prefixed with -99
(so error code 1001 becomes -991001) to distinguish them from other TS
errors.

A function is provided which will read TS diagnostic output and convert
the TS errors to NG errors if they match this negative error code
format.

PR Close #25647
This commit is contained in:
Alex Rickabaugh
2018-08-23 14:34:55 -07:00
committed by Misko Hevery
parent b424b3187e
commit 38f624d7e3
19 changed files with 331 additions and 85 deletions

View File

@ -88,9 +88,10 @@ export class NgtscProgram implements api.Program {
}
getNgSemanticDiagnostics(
fileName?: string|undefined,
cancellationToken?: ts.CancellationToken|undefined): ReadonlyArray<api.Diagnostic> {
return [];
fileName?: string|undefined, cancellationToken?: ts.CancellationToken|
undefined): ReadonlyArray<ts.Diagnostic|api.Diagnostic> {
const compilation = this.ensureAnalyzed();
return compilation.diagnostics;
}
async loadNgStructureAsync(): Promise<void> {
@ -117,6 +118,16 @@ export class NgtscProgram implements api.Program {
throw new Error('Method not implemented.');
}
private ensureAnalyzed(): IvyCompilation {
if (this.compilation === undefined) {
this.compilation = this.makeCompilation();
this.tsProgram.getSourceFiles()
.filter(file => !file.fileName.endsWith('.d.ts'))
.forEach(file => this.compilation !.analyzeSync(file));
}
return this.compilation;
}
emit(opts?: {
emitFlags?: api.EmitFlags,
cancellationToken?: ts.CancellationToken,
@ -126,12 +137,7 @@ export class NgtscProgram implements api.Program {
}): ts.EmitResult {
const emitCallback = opts && opts.emitCallback || defaultEmitCallback;
if (this.compilation === undefined) {
this.compilation = this.makeCompilation();
this.tsProgram.getSourceFiles()
.filter(file => !file.fileName.endsWith('.d.ts'))
.forEach(file => this.compilation !.analyzeSync(file));
}
this.ensureAnalyzed();
// Since there is no .d.ts transformation API, .d.ts files are transformed during write.
const writeFile: ts.WriteFileCallback =