refactor(compiler): change ngc error handling
Do not print stack trace for user errors Print stack trace for compiler internal errors
This commit is contained in:
parent
75d1617b63
commit
9761db5ac2
|
@ -22,14 +22,24 @@ function codegen(
|
||||||
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen();
|
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function main(args: any, consoleError: any): Promise<number> {
|
||||||
|
const project = args.p || args.project || '.';
|
||||||
|
const cliOptions = new tsc.NgcCliOptions(args);
|
||||||
|
|
||||||
|
return tsc.main(project, cliOptions, codegen).then(() => 0).catch(e => {
|
||||||
|
if (e instanceof tsc.UserError) {
|
||||||
|
consoleError(e.message);
|
||||||
|
return Promise.resolve(0);
|
||||||
|
} else {
|
||||||
|
consoleError(e.stack);
|
||||||
|
consoleError('Compilation failed');
|
||||||
|
return Promise.resolve(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// CLI entry point
|
// CLI entry point
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
const args = require('minimist')(process.argv.slice(2));
|
const args = require('minimist')(process.argv.slice(2));
|
||||||
const project = args.p || args.project || '.';
|
main(args, console.error).then((exitCode: number) => process.exit(exitCode));
|
||||||
const cliOptions = new tsc.NgcCliOptions(args);
|
}
|
||||||
tsc.main(project, cliOptions, codegen).then(exitCode => process.exit(exitCode)).catch(e => {
|
|
||||||
console.error(e.stack);
|
|
||||||
console.error('Compilation failed');
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {makeTempDir} from '@angular/tsc-wrapped/test/test_support';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
import {main} from '../src/main';
|
||||||
|
import {ReflectionCapabilities, reflector} from './private_import_core';
|
||||||
|
|
||||||
|
|
||||||
|
describe('compiler-cli', () => {
|
||||||
|
let basePath: string;
|
||||||
|
let write: (fileName: string, content: string) => void;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
basePath = makeTempDir();
|
||||||
|
write = (fileName: string, content: string) => {
|
||||||
|
fs.writeFileSync(path.join(basePath, fileName), content, {encoding: 'utf-8'});
|
||||||
|
};
|
||||||
|
write('tsconfig.json', `{
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"types": [],
|
||||||
|
"outDir": "built",
|
||||||
|
"declaration": true,
|
||||||
|
"module": "es2015"
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"annotateForClosureCompiler": true
|
||||||
|
},
|
||||||
|
"files": ["test.ts"]
|
||||||
|
}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Restore reflector since AoT compiler will update it with a new static reflector
|
||||||
|
afterEach(() => { reflector.updateCapabilities(new ReflectionCapabilities()); });
|
||||||
|
|
||||||
|
it('should compile without errors', (done) => {
|
||||||
|
write('test.ts', 'export const A = 1;');
|
||||||
|
|
||||||
|
const mockConsole = {error: {}};
|
||||||
|
|
||||||
|
spyOn(mockConsole, 'error');
|
||||||
|
|
||||||
|
main({p: basePath}, mockConsole.error)
|
||||||
|
.then((exitCode) => {
|
||||||
|
expect(mockConsole.error).not.toHaveBeenCalled();
|
||||||
|
expect(exitCode).toEqual(0);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(e => done.fail(e));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not print the stack trace if user input file does not exist', (done) => {
|
||||||
|
const mockConsole = {error: {}};
|
||||||
|
|
||||||
|
spyOn(mockConsole, 'error');
|
||||||
|
|
||||||
|
main({p: basePath}, mockConsole.error)
|
||||||
|
.then((exitCode) => {
|
||||||
|
expect(mockConsole.error).toHaveBeenCalled();
|
||||||
|
expect(mockConsole.error).not.toHaveBeenCalledWith('Compilation failed');
|
||||||
|
expect(exitCode).toEqual(0);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(e => done.fail(e));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not print the stack trace if user input file is malformed', (done) => {
|
||||||
|
write('test.ts', 'foo bar');
|
||||||
|
|
||||||
|
const mockConsole = {error: {}};
|
||||||
|
|
||||||
|
spyOn(mockConsole, 'error');
|
||||||
|
|
||||||
|
main({p: basePath}, mockConsole.error)
|
||||||
|
.then((exitCode) => {
|
||||||
|
expect(mockConsole.error).toHaveBeenCalled();
|
||||||
|
expect(mockConsole.error).not.toHaveBeenCalledWith('Compilation failed');
|
||||||
|
expect(exitCode).toEqual(0);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(e => done.fail(e));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should print the stack trace on compiler internal errors', (done) => {
|
||||||
|
write('test.ts', 'export const A = 1;');
|
||||||
|
|
||||||
|
const mockConsole = {error: {}};
|
||||||
|
|
||||||
|
spyOn(mockConsole, 'error');
|
||||||
|
|
||||||
|
main({p: 'not-exist'}, mockConsole.error)
|
||||||
|
.then((exitCode) => {
|
||||||
|
expect(mockConsole.error).toHaveBeenCalled();
|
||||||
|
expect(mockConsole.error).toHaveBeenCalledWith('Compilation failed');
|
||||||
|
expect(exitCode).toEqual(1);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(e => done.fail(e));
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,13 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {__core_private__ as r} from '@angular/core';
|
||||||
|
|
||||||
|
export type ReflectionCapabilities = typeof r._ReflectionCapabilities;
|
||||||
|
export var ReflectionCapabilities: typeof r.ReflectionCapabilities = r.ReflectionCapabilities;
|
||||||
|
export var reflector: typeof r.reflector = r.reflector;
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export {DecoratorDownlevelCompilerHost, MetadataWriterHost} from './src/compiler_host';
|
export {DecoratorDownlevelCompilerHost, MetadataWriterHost} from './src/compiler_host';
|
||||||
export {CodegenExtension, main} from './src/main';
|
export {CodegenExtension, UserError, main} from './src/main';
|
||||||
|
|
||||||
export {default as AngularCompilerOptions} from './src/options';
|
export {default as AngularCompilerOptions} from './src/options';
|
||||||
export * from './src/cli_options';
|
export * from './src/cli_options';
|
||||||
|
|
|
@ -16,6 +16,8 @@ import NgOptions from './options';
|
||||||
import {MetadataWriterHost, DecoratorDownlevelCompilerHost, TsickleCompilerHost} from './compiler_host';
|
import {MetadataWriterHost, DecoratorDownlevelCompilerHost, TsickleCompilerHost} from './compiler_host';
|
||||||
import {CliOptions} from './cli_options';
|
import {CliOptions} from './cli_options';
|
||||||
|
|
||||||
|
export {UserError} from './tsc';
|
||||||
|
|
||||||
export type CodegenExtension =
|
export type CodegenExtension =
|
||||||
(ngOptions: NgOptions, cliOptions: CliOptions, program: ts.Program, host: ts.CompilerHost) =>
|
(ngOptions: NgOptions, cliOptions: CliOptions, program: ts.Program, host: ts.CompilerHost) =>
|
||||||
Promise<void>;
|
Promise<void>;
|
||||||
|
|
|
@ -24,6 +24,15 @@ export interface CompilerInterface {
|
||||||
emit(program: ts.Program): number;
|
emit(program: ts.Program): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class UserError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message);
|
||||||
|
this.message = message;
|
||||||
|
this.name = 'UserError';
|
||||||
|
this.stack = new Error().stack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
|
|
||||||
function debug(msg: string, ...o: any[]) {
|
function debug(msg: string, ...o: any[]) {
|
||||||
|
@ -48,7 +57,7 @@ export function formatDiagnostics(diags: ts.Diagnostic[]): string {
|
||||||
|
|
||||||
export function check(diags: ts.Diagnostic[]) {
|
export function check(diags: ts.Diagnostic[]) {
|
||||||
if (diags && diags.length && diags[0]) {
|
if (diags && diags.length && diags[0]) {
|
||||||
throw new Error(formatDiagnostics(diags));
|
throw new UserError(formatDiagnostics(diags));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue