170 lines
6.4 KiB
JavaScript
170 lines
6.4 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* @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
|
||
*/
|
||
|
||
// Must be imported first, because Angular decorators throw on load.
|
||
import 'reflect-metadata';
|
||
|
||
import * as ts from 'typescript';
|
||
import * as tsc from '@angular/tsc-wrapped';
|
||
import * as fs from 'fs';
|
||
import * as path from 'path';
|
||
import * as tsickle from 'tsickle';
|
||
import * as api from './transformers/api';
|
||
import * as ngc from './transformers/entry_points';
|
||
|
||
import {calcProjectFileAndBasePath, exitCodeFromResult, performCompilation, readConfiguration, formatDiagnostics, Diagnostics, ParsedConfiguration, PerformCompilationResult} from './perform_compile';
|
||
import {performWatchCompilation, createPerformWatchHost} from './perform_watch';
|
||
import {isSyntaxError} from '@angular/compiler';
|
||
import {CodeGenerator} from './codegen';
|
||
|
||
export function main(
|
||
args: string[], consoleError: (s: string) => void = console.error): Promise<number> {
|
||
const parsedArgs = require('minimist')(args);
|
||
if (parsedArgs.w || parsedArgs.watch) {
|
||
const result = watchMode(parsedArgs, consoleError);
|
||
return Promise.resolve(exitCodeFromResult(result.firstCompileResult));
|
||
}
|
||
const {rootNames, options, errors: configErrors} = readCommandLineAndConfiguration(parsedArgs);
|
||
if (configErrors.length) {
|
||
return Promise.resolve(reportErrorsAndExit(options, configErrors, consoleError));
|
||
}
|
||
if (options.disableTransformerPipeline) {
|
||
return disabledTransformerPipelineNgcMain(parsedArgs, consoleError);
|
||
}
|
||
const {diagnostics: compileDiags} =
|
||
performCompilation({rootNames, options, emitCallback: createEmitCallback(options)});
|
||
return Promise.resolve(reportErrorsAndExit(options, compileDiags, consoleError));
|
||
}
|
||
|
||
export function mainSync(
|
||
args: string[], consoleError: (s: string) => void = console.error): number {
|
||
const parsedArgs = require('minimist')(args);
|
||
const {rootNames, options, errors: configErrors} = readCommandLineAndConfiguration(parsedArgs);
|
||
if (configErrors.length) {
|
||
return reportErrorsAndExit(options, configErrors, consoleError);
|
||
}
|
||
const {diagnostics: compileDiags} =
|
||
performCompilation({rootNames, options, emitCallback: createEmitCallback(options)});
|
||
return reportErrorsAndExit(options, compileDiags, consoleError);
|
||
}
|
||
|
||
function createEmitCallback(options: api.CompilerOptions): api.TsEmitCallback {
|
||
const tsickleOptions: tsickle.TransformerOptions = {
|
||
googmodule: false,
|
||
untyped: true,
|
||
convertIndexImportShorthand: true,
|
||
transformDecorators: options.annotationsAs !== 'decorators',
|
||
transformTypesToClosure: options.annotateForClosureCompiler,
|
||
};
|
||
|
||
const tsickleHost: tsickle.TransformerHost = {
|
||
shouldSkipTsickleProcessing: (fileName) => /\.d\.ts$/.test(fileName),
|
||
pathToModuleName: (context, importPath) => '',
|
||
shouldIgnoreWarningsForPath: (filePath) => false,
|
||
fileNameToModuleId: (fileName) => fileName,
|
||
};
|
||
|
||
return ({
|
||
program,
|
||
targetSourceFile,
|
||
writeFile,
|
||
cancellationToken,
|
||
emitOnlyDtsFiles,
|
||
customTransformers = {},
|
||
host,
|
||
options
|
||
}) =>
|
||
tsickle.emitWithTsickle(
|
||
program, tsickleHost, tsickleOptions, host, options, targetSourceFile, writeFile,
|
||
cancellationToken, emitOnlyDtsFiles, {
|
||
beforeTs: customTransformers.before,
|
||
afterTs: customTransformers.after,
|
||
});
|
||
}
|
||
|
||
function projectOf(args: any): string {
|
||
return (args && (args.p || args.project)) || '.';
|
||
}
|
||
|
||
function readCommandLineAndConfiguration(args: any): ParsedConfiguration {
|
||
const project = projectOf(args);
|
||
const allDiagnostics: Diagnostics = [];
|
||
const config = readConfiguration(project);
|
||
const options = mergeCommandLineParams(args, config.options);
|
||
if (options.locale) {
|
||
options.i18nInLocale = options.locale;
|
||
}
|
||
return {project, rootNames: config.rootNames, options, errors: config.errors};
|
||
}
|
||
|
||
function reportErrorsAndExit(
|
||
options: api.CompilerOptions, allDiagnostics: Diagnostics,
|
||
consoleError: (s: string) => void = console.error): number {
|
||
const exitCode = allDiagnostics.some(d => d.category === ts.DiagnosticCategory.Error) ? 1 : 0;
|
||
if (allDiagnostics.length) {
|
||
consoleError(formatDiagnostics(options, allDiagnostics));
|
||
}
|
||
return exitCode;
|
||
}
|
||
|
||
export function watchMode(args: any, consoleError: (s: string) => void) {
|
||
const project = projectOf(args);
|
||
const {projectFile, basePath} = calcProjectFileAndBasePath(project);
|
||
const config = readConfiguration(project);
|
||
return performWatchCompilation(createPerformWatchHost(projectFile, diagnostics => {
|
||
consoleError(formatDiagnostics(config.options, diagnostics));
|
||
}, options => createEmitCallback(options)));
|
||
}
|
||
|
||
function mergeCommandLineParams(
|
||
cliArgs: {[k: string]: string}, options: api.CompilerOptions): api.CompilerOptions {
|
||
// TODO: also merge in tsc command line parameters by calling
|
||
// ts.readCommandLine.
|
||
if (cliArgs.i18nFile) options.i18nInFile = cliArgs.i18nFile;
|
||
if (cliArgs.i18nFormat) options.i18nInFormat = cliArgs.i18nFormat;
|
||
if (cliArgs.locale) options.i18nInLocale = cliArgs.locale;
|
||
const mt = cliArgs.missingTranslation;
|
||
if (mt === 'error' || mt === 'warning' || mt === 'ignore') {
|
||
options.i18nInMissingTranslations = mt;
|
||
}
|
||
return options;
|
||
}
|
||
|
||
function disabledTransformerPipelineNgcMain(
|
||
args: any, consoleError: (s: string) => void = console.error): Promise<number> {
|
||
const cliOptions = new tsc.NgcCliOptions(args);
|
||
const project = args.p || args.project || '.';
|
||
return tsc.main(project, cliOptions, disabledTransformerPipelineCodegen)
|
||
.then(() => 0)
|
||
.catch(e => {
|
||
if (e instanceof tsc.UserError || isSyntaxError(e)) {
|
||
consoleError(e.message);
|
||
} else {
|
||
consoleError(e.stack);
|
||
}
|
||
return Promise.resolve(1);
|
||
});
|
||
}
|
||
|
||
function disabledTransformerPipelineCodegen(
|
||
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.NgcCliOptions, program: ts.Program,
|
||
host: ts.CompilerHost) {
|
||
if (ngOptions.enableSummariesForJit === undefined) {
|
||
// default to false
|
||
ngOptions.enableSummariesForJit = false;
|
||
}
|
||
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen();
|
||
}
|
||
|
||
// CLI entry point
|
||
if (require.main === module) {
|
||
const args = process.argv.slice(2);
|
||
main(args).then((exitCode: number) => process.exitCode = exitCode);
|
||
}
|