mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-24 20:19:25 -05:00
Merge baselining and tsc logic into one
This commit is contained in:
@@ -1227,7 +1227,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function parseBuildCommand(args: string[]): ParsedBuildCommand {
|
||||
export function parseBuildCommand(args: readonly string[]): ParsedBuildCommand {
|
||||
let buildOptionNameMap: OptionNameMap | undefined;
|
||||
const returnBuildOptionNameMap = () => (buildOptionNameMap || (buildOptionNameMap = createOptionNameMap(buildOpts)));
|
||||
const { options, fileNames: projects, errors } = parseCommandLineWorker(returnBuildOptionNameMap, [
|
||||
@@ -1258,125 +1258,12 @@ namespace ts {
|
||||
return { buildOptions, projects, errors };
|
||||
}
|
||||
|
||||
function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string {
|
||||
/* @internal */
|
||||
export function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string {
|
||||
const diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
|
||||
return <string>diagnostic.messageText;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function printVersion() {
|
||||
sys.write(getDiagnosticText(Diagnostics.Version_0, version) + sys.newLine);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function printHelp(optionsList: readonly CommandLineOption[], syntaxPrefix = "") {
|
||||
const output: string[] = [];
|
||||
|
||||
// We want to align our "syntax" and "examples" commands to a certain margin.
|
||||
const syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
|
||||
const examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
|
||||
let marginLength = Math.max(syntaxLength, examplesLength);
|
||||
|
||||
// Build up the syntactic skeleton.
|
||||
let syntax = makePadding(marginLength - syntaxLength);
|
||||
syntax += `tsc ${syntaxPrefix}[${getDiagnosticText(Diagnostics.options)}] [${getDiagnosticText(Diagnostics.file)}...]`;
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Syntax_Colon_0, syntax));
|
||||
output.push(sys.newLine + sys.newLine);
|
||||
|
||||
// Build up the list of examples.
|
||||
const padding = makePadding(marginLength);
|
||||
output.push(getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine);
|
||||
output.push(padding + "tsc --outFile file.js file.ts" + sys.newLine);
|
||||
output.push(padding + "tsc @args.txt" + sys.newLine);
|
||||
output.push(padding + "tsc --build tsconfig.json" + sys.newLine);
|
||||
output.push(sys.newLine);
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine);
|
||||
|
||||
// We want our descriptions to align at the same column in our output,
|
||||
// so we keep track of the longest option usage string.
|
||||
marginLength = 0;
|
||||
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
|
||||
const descriptionColumn: string[] = [];
|
||||
|
||||
const optionsDescriptionMap = createMap<string[]>(); // Map between option.description and list of option.type if it is a kind
|
||||
|
||||
for (const option of optionsList) {
|
||||
// If an option lacks a description,
|
||||
// it is not officially supported.
|
||||
if (!option.description) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let usageText = " ";
|
||||
if (option.shortName) {
|
||||
usageText += "-" + option.shortName;
|
||||
usageText += getParamType(option);
|
||||
usageText += ", ";
|
||||
}
|
||||
|
||||
usageText += "--" + option.name;
|
||||
usageText += getParamType(option);
|
||||
|
||||
usageColumn.push(usageText);
|
||||
let description: string;
|
||||
|
||||
if (option.name === "lib") {
|
||||
description = getDiagnosticText(option.description);
|
||||
const element = (<CommandLineOptionOfListType>option).element;
|
||||
const typeMap = <Map<number | string>>element.type;
|
||||
optionsDescriptionMap.set(description, arrayFrom(typeMap.keys()).map(key => `'${key}'`));
|
||||
}
|
||||
else {
|
||||
description = getDiagnosticText(option.description);
|
||||
}
|
||||
|
||||
descriptionColumn.push(description);
|
||||
|
||||
// Set the new margin for the description column if necessary.
|
||||
marginLength = Math.max(usageText.length, marginLength);
|
||||
}
|
||||
|
||||
// Special case that can't fit in the loop.
|
||||
const usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
|
||||
usageColumn.push(usageText);
|
||||
descriptionColumn.push(getDiagnosticText(Diagnostics.Insert_command_line_options_and_files_from_a_file));
|
||||
marginLength = Math.max(usageText.length, marginLength);
|
||||
|
||||
// Print out each row, aligning all the descriptions on the same column.
|
||||
for (let i = 0; i < usageColumn.length; i++) {
|
||||
const usage = usageColumn[i];
|
||||
const description = descriptionColumn[i];
|
||||
const kindsList = optionsDescriptionMap.get(description);
|
||||
output.push(usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine);
|
||||
|
||||
if (kindsList) {
|
||||
output.push(makePadding(marginLength + 4));
|
||||
for (const kind of kindsList) {
|
||||
output.push(kind + " ");
|
||||
}
|
||||
output.push(sys.newLine);
|
||||
}
|
||||
}
|
||||
|
||||
for (const line of output) {
|
||||
sys.write(line);
|
||||
}
|
||||
return;
|
||||
|
||||
function getParamType(option: CommandLineOption) {
|
||||
if (option.paramType !== undefined) {
|
||||
return " " + getDiagnosticText(option.paramType);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function makePadding(paddingLength: number): string {
|
||||
return Array(paddingLength + 1).join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
export type DiagnosticReporter = (diagnostic: Diagnostic) => void;
|
||||
/**
|
||||
* Reports config file diagnostics
|
||||
@@ -1801,6 +1688,12 @@ namespace ts {
|
||||
references: readonly ProjectReference[] | undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface ConvertToTSConfigHost {
|
||||
getCurrentDirectory(): string;
|
||||
useCaseSensitiveFileNames: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an uncommented, complete tsconfig for use with "--showConfig"
|
||||
* @param configParseResult options to be generated into tsconfig.json
|
||||
@@ -1808,7 +1701,7 @@ namespace ts {
|
||||
* @param host provides current directory and case sensitivity services
|
||||
*/
|
||||
/** @internal */
|
||||
export function convertToTSConfig(configParseResult: ParsedCommandLine, configFileName: string, host: { getCurrentDirectory(): string, useCaseSensitiveFileNames: boolean }): TSConfig {
|
||||
export function convertToTSConfig(configParseResult: ParsedCommandLine, configFileName: string, host: ConvertToTSConfigHost): TSConfig {
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
|
||||
const files = map(
|
||||
filter(
|
||||
@@ -1816,7 +1709,8 @@ namespace ts {
|
||||
(!configParseResult.configFileSpecs || !configParseResult.configFileSpecs.validatedIncludeSpecs) ? _ => true : matchesSpecs(
|
||||
configFileName,
|
||||
configParseResult.configFileSpecs.validatedIncludeSpecs,
|
||||
configParseResult.configFileSpecs.validatedExcludeSpecs
|
||||
configParseResult.configFileSpecs.validatedExcludeSpecs,
|
||||
host,
|
||||
)
|
||||
),
|
||||
f => getRelativePathFromFile(getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), getNormalizedAbsolutePath(f, host.getCurrentDirectory()), getCanonicalFileName)
|
||||
@@ -1854,11 +1748,11 @@ namespace ts {
|
||||
return specs;
|
||||
}
|
||||
|
||||
function matchesSpecs(path: string, includeSpecs: readonly string[] | undefined, excludeSpecs: readonly string[] | undefined): (path: string) => boolean {
|
||||
function matchesSpecs(path: string, includeSpecs: readonly string[] | undefined, excludeSpecs: readonly string[] | undefined, host: ConvertToTSConfigHost): (path: string) => boolean {
|
||||
if (!includeSpecs) return _ => true;
|
||||
const patterns = getFileMatcherPatterns(path, excludeSpecs, includeSpecs, sys.useCaseSensitiveFileNames, sys.getCurrentDirectory());
|
||||
const excludeRe = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, sys.useCaseSensitiveFileNames);
|
||||
const includeRe = patterns.includeFilePattern && getRegexFromPattern(patterns.includeFilePattern, sys.useCaseSensitiveFileNames);
|
||||
const patterns = getFileMatcherPatterns(path, excludeSpecs, includeSpecs, host.useCaseSensitiveFileNames, host.getCurrentDirectory());
|
||||
const excludeRe = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, host.useCaseSensitiveFileNames);
|
||||
const includeRe = patterns.includeFilePattern && getRegexFromPattern(patterns.includeFilePattern, host.useCaseSensitiveFileNames);
|
||||
if (includeRe) {
|
||||
if (excludeRe) {
|
||||
return path => !(includeRe.test(path) && !excludeRe.test(path));
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace ts {
|
||||
/** Parses config file using System interface */
|
||||
export function parseConfigFileWithSystem(configFileName: string, optionsToExtend: CompilerOptions, system: System, reportDiagnostic: DiagnosticReporter) {
|
||||
const host: ParseConfigFileHost = <any>system;
|
||||
host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(sys, reportDiagnostic, diagnostic);
|
||||
host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, reportDiagnostic, diagnostic);
|
||||
const result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host);
|
||||
host.onUnRecoverableConfigFileDiagnostic = undefined!; // TODO: GH#18217
|
||||
return result;
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
"unittests/services/extract/helpers.ts",
|
||||
"unittests/tsbuild/helpers.ts",
|
||||
"../tsc/executeCommandLine.ts",
|
||||
"unittests/tsc/helpers.ts",
|
||||
"unittests/tscWatch/helpers.ts",
|
||||
"unittests/tsserver/helpers.ts",
|
||||
|
||||
@@ -3,167 +3,6 @@ namespace ts {
|
||||
writtenFiles: Map<true>;
|
||||
baseLine(): void;
|
||||
};
|
||||
function executeCommandLine(sys: TscCompileSystem, commandLineArgs: readonly string[]) {
|
||||
if (isBuild(commandLineArgs)) {
|
||||
return performBuild(sys, commandLineArgs.slice(1));
|
||||
}
|
||||
|
||||
const reportDiagnostic = createDiagnosticReporter(sys);
|
||||
const commandLine = parseCommandLine(commandLineArgs, path => sys.readFile(path));
|
||||
if (commandLine.options.build) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_build_must_be_the_first_command_line_argument));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
if (commandLine.errors.length > 0) {
|
||||
commandLine.errors.forEach(reportDiagnostic);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
let configFileName: string | undefined;
|
||||
if (commandLine.options.project) {
|
||||
if (commandLine.fileNames.length !== 0) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
const fileOrDirectory = normalizePath(commandLine.options.project);
|
||||
if (!fileOrDirectory /* current directory "." */ || sys.directoryExists(fileOrDirectory)) {
|
||||
configFileName = combinePaths(fileOrDirectory, "tsconfig.json");
|
||||
if (!sys.fileExists(configFileName)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
}
|
||||
else {
|
||||
configFileName = fileOrDirectory;
|
||||
if (!sys.fileExists(configFileName)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (commandLine.fileNames.length === 0) {
|
||||
const searchPath = normalizePath(sys.getCurrentDirectory());
|
||||
configFileName = findConfigFile(searchPath, sys.fileExists);
|
||||
}
|
||||
|
||||
Debug.assert(commandLine.fileNames.length !== 0 || !!configFileName);
|
||||
|
||||
const currentDirectory = sys.getCurrentDirectory();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(sys.useCaseSensitiveFileNames);
|
||||
const commandLineOptions = convertToOptionsWithAbsolutePaths(
|
||||
commandLine.options,
|
||||
fileName => toPath(fileName, currentDirectory, getCanonicalFileName)
|
||||
);
|
||||
|
||||
if (configFileName) {
|
||||
const configParseResult = Debug.assertDefined(parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic));
|
||||
if (isIncrementalCompilation(configParseResult.options)) {
|
||||
performIncrementalCompilation(sys, configParseResult);
|
||||
}
|
||||
else {
|
||||
performCompilation(sys, configParseResult);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isIncrementalCompilation(commandLine.options)) {
|
||||
performIncrementalCompilation(sys, {
|
||||
...commandLine,
|
||||
options: commandLineOptions
|
||||
});
|
||||
}
|
||||
else {
|
||||
performCompilation(sys, {
|
||||
...commandLine,
|
||||
options: commandLineOptions
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createReportErrorSummary(sys: TscCompileSystem, options: CompilerOptions): ReportEmitErrorSummary | undefined {
|
||||
return options.pretty ?
|
||||
errorCount => sys.write(getErrorSummaryText(errorCount, sys.newLine)) :
|
||||
undefined;
|
||||
}
|
||||
|
||||
function performCompilation(sys: TscCompileSystem, config: ParsedCommandLine) {
|
||||
const { fileNames, options, projectReferences } = config;
|
||||
const reportDiagnostic = createDiagnosticReporter(sys, options.pretty);
|
||||
const host = createCompilerHostWorker(options, /*setParentPos*/ undefined, sys);
|
||||
fakes.patchHostForBuildInfoReadWrite(host);
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
|
||||
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName));
|
||||
const program = createProgram({
|
||||
rootNames: fileNames,
|
||||
options,
|
||||
projectReferences,
|
||||
host,
|
||||
configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config)
|
||||
});
|
||||
const exitStatus = emitFilesAndReportErrorsAndGetExitStatus(
|
||||
program,
|
||||
reportDiagnostic,
|
||||
s => sys.write(s + sys.newLine),
|
||||
createReportErrorSummary(sys, options)
|
||||
);
|
||||
baselineBuildInfo([config], sys.vfs, sys.writtenFiles);
|
||||
return sys.exit(exitStatus);
|
||||
}
|
||||
|
||||
function performIncrementalCompilation(sys: TscCompileSystem, config: ParsedCommandLine) {
|
||||
const reportDiagnostic = createDiagnosticReporter(sys, config.options.pretty);
|
||||
const { options, fileNames, projectReferences } = config;
|
||||
const host = createIncrementalCompilerHost(options, sys);
|
||||
fakes.patchHostForBuildInfoReadWrite(host);
|
||||
const exitCode = ts.performIncrementalCompilation({
|
||||
host,
|
||||
system: sys,
|
||||
rootNames: fileNames,
|
||||
options,
|
||||
configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config),
|
||||
projectReferences,
|
||||
reportDiagnostic,
|
||||
reportErrorSummary: createReportErrorSummary(sys, options),
|
||||
});
|
||||
baselineBuildInfo([config], sys.vfs, sys.writtenFiles);
|
||||
return sys.exit(exitCode);
|
||||
}
|
||||
|
||||
function performBuild(sys: TscCompileSystem, args: string[]) {
|
||||
const { buildOptions, projects, errors } = parseBuildCommand(args);
|
||||
const reportDiagnostic = createDiagnosticReporter(sys, buildOptions.pretty);
|
||||
|
||||
if (errors.length > 0) {
|
||||
errors.forEach(reportDiagnostic);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
Debug.assert(projects.length !== 0);
|
||||
|
||||
const buildHost = createSolutionBuilderHost(
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
reportDiagnostic,
|
||||
createBuilderStatusReporter(sys, buildOptions.pretty),
|
||||
createReportErrorSummary(sys, buildOptions)
|
||||
);
|
||||
fakes.patchSolutionBuilderHost(buildHost, sys);
|
||||
const builder = createSolutionBuilder(buildHost, projects, buildOptions);
|
||||
const exitCode = buildOptions.clean ? builder.clean() : builder.build();
|
||||
baselineBuildInfo(builder.getAllParsedConfigs(), sys.vfs, sys.writtenFiles);
|
||||
return sys.exit(exitCode);
|
||||
}
|
||||
|
||||
function isBuild(commandLineArgs: readonly string[]) {
|
||||
if (commandLineArgs.length > 0 && commandLineArgs[0].charCodeAt(0) === CharacterCodes.minus) {
|
||||
const firstOption = commandLineArgs[0].slice(commandLineArgs[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
|
||||
return firstOption === "build" || firstOption === "b";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export enum BuildKind {
|
||||
Initial = "initial-build",
|
||||
@@ -221,7 +60,16 @@ namespace ts {
|
||||
|
||||
sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`);
|
||||
sys.exit = exitCode => sys.exitCode = exitCode;
|
||||
executeCommandLine(sys, commandLineArgs);
|
||||
ts.executeCommandLine(
|
||||
sys,
|
||||
{
|
||||
onCompilerHostCreate: host => fakes.patchHostForBuildInfoReadWrite(host),
|
||||
onCompilationComplete: config => baselineBuildInfo([config], sys.vfs, sys.writtenFiles),
|
||||
onSolutionBuilderHostCreate: host => fakes.patchSolutionBuilderHost(host, sys),
|
||||
onSolutionBuildComplete: configs => baselineBuildInfo(configs, sys.vfs, sys.writtenFiles),
|
||||
},
|
||||
commandLineArgs,
|
||||
);
|
||||
sys.write(`exitCode:: ExitStatus.${ExitStatus[sys.exitCode as ExitStatus]}\n`);
|
||||
if (baselineReadFileCalls) {
|
||||
sys.write(`readFiles:: ${JSON.stringify(actualReadFileMap, /*replacer*/ undefined, " ")} `);
|
||||
|
||||
725
src/tsc/executeCommandLine.ts
Normal file
725
src/tsc/executeCommandLine.ts
Normal file
@@ -0,0 +1,725 @@
|
||||
namespace ts {
|
||||
interface Statistic {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
function countLines(program: Program): number {
|
||||
let count = 0;
|
||||
forEach(program.getSourceFiles(), file => {
|
||||
count += getLineStarts(file).length;
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
function updateReportDiagnostic(
|
||||
sys: System,
|
||||
existing: DiagnosticReporter,
|
||||
options: CompilerOptions | BuildOptions
|
||||
): DiagnosticReporter {
|
||||
return shouldBePretty(sys, options) ?
|
||||
createDiagnosticReporter(sys, /*pretty*/ true) :
|
||||
existing;
|
||||
}
|
||||
|
||||
function defaultIsPretty(sys: System) {
|
||||
return !!sys.writeOutputIsTTY && sys.writeOutputIsTTY();
|
||||
}
|
||||
|
||||
function shouldBePretty(sys: System, options: CompilerOptions | BuildOptions) {
|
||||
if (!options || typeof options.pretty === "undefined") {
|
||||
return defaultIsPretty(sys);
|
||||
}
|
||||
return options.pretty;
|
||||
}
|
||||
|
||||
function padLeft(s: string, length: number) {
|
||||
while (s.length < length) {
|
||||
s = " " + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function padRight(s: string, length: number) {
|
||||
while (s.length < length) {
|
||||
s = s + " ";
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function getOptionsForHelp(commandLine: ParsedCommandLine) {
|
||||
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
|
||||
return !!commandLine.options.all ?
|
||||
sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) :
|
||||
filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView);
|
||||
}
|
||||
|
||||
function printVersion(sys: System) {
|
||||
sys.write(getDiagnosticText(Diagnostics.Version_0, version) + sys.newLine);
|
||||
}
|
||||
|
||||
function printHelp(sys: System, optionsList: readonly CommandLineOption[], syntaxPrefix = "") {
|
||||
const output: string[] = [];
|
||||
|
||||
// We want to align our "syntax" and "examples" commands to a certain margin.
|
||||
const syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
|
||||
const examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
|
||||
let marginLength = Math.max(syntaxLength, examplesLength);
|
||||
|
||||
// Build up the syntactic skeleton.
|
||||
let syntax = makePadding(marginLength - syntaxLength);
|
||||
syntax += `tsc ${syntaxPrefix}[${getDiagnosticText(Diagnostics.options)}] [${getDiagnosticText(Diagnostics.file)}...]`;
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Syntax_Colon_0, syntax));
|
||||
output.push(sys.newLine + sys.newLine);
|
||||
|
||||
// Build up the list of examples.
|
||||
const padding = makePadding(marginLength);
|
||||
output.push(getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine);
|
||||
output.push(padding + "tsc --outFile file.js file.ts" + sys.newLine);
|
||||
output.push(padding + "tsc @args.txt" + sys.newLine);
|
||||
output.push(padding + "tsc --build tsconfig.json" + sys.newLine);
|
||||
output.push(sys.newLine);
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine);
|
||||
|
||||
// We want our descriptions to align at the same column in our output,
|
||||
// so we keep track of the longest option usage string.
|
||||
marginLength = 0;
|
||||
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
|
||||
const descriptionColumn: string[] = [];
|
||||
|
||||
const optionsDescriptionMap = createMap<string[]>(); // Map between option.description and list of option.type if it is a kind
|
||||
|
||||
for (const option of optionsList) {
|
||||
// If an option lacks a description,
|
||||
// it is not officially supported.
|
||||
if (!option.description) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let usageText = " ";
|
||||
if (option.shortName) {
|
||||
usageText += "-" + option.shortName;
|
||||
usageText += getParamType(option);
|
||||
usageText += ", ";
|
||||
}
|
||||
|
||||
usageText += "--" + option.name;
|
||||
usageText += getParamType(option);
|
||||
|
||||
usageColumn.push(usageText);
|
||||
let description: string;
|
||||
|
||||
if (option.name === "lib") {
|
||||
description = getDiagnosticText(option.description);
|
||||
const element = (<CommandLineOptionOfListType>option).element;
|
||||
const typeMap = <Map<number | string>>element.type;
|
||||
optionsDescriptionMap.set(description, arrayFrom(typeMap.keys()).map(key => `'${key}'`));
|
||||
}
|
||||
else {
|
||||
description = getDiagnosticText(option.description);
|
||||
}
|
||||
|
||||
descriptionColumn.push(description);
|
||||
|
||||
// Set the new margin for the description column if necessary.
|
||||
marginLength = Math.max(usageText.length, marginLength);
|
||||
}
|
||||
|
||||
// Special case that can't fit in the loop.
|
||||
const usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
|
||||
usageColumn.push(usageText);
|
||||
descriptionColumn.push(getDiagnosticText(Diagnostics.Insert_command_line_options_and_files_from_a_file));
|
||||
marginLength = Math.max(usageText.length, marginLength);
|
||||
|
||||
// Print out each row, aligning all the descriptions on the same column.
|
||||
for (let i = 0; i < usageColumn.length; i++) {
|
||||
const usage = usageColumn[i];
|
||||
const description = descriptionColumn[i];
|
||||
const kindsList = optionsDescriptionMap.get(description);
|
||||
output.push(usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine);
|
||||
|
||||
if (kindsList) {
|
||||
output.push(makePadding(marginLength + 4));
|
||||
for (const kind of kindsList) {
|
||||
output.push(kind + " ");
|
||||
}
|
||||
output.push(sys.newLine);
|
||||
}
|
||||
}
|
||||
|
||||
for (const line of output) {
|
||||
sys.write(line);
|
||||
}
|
||||
return;
|
||||
|
||||
function getParamType(option: CommandLineOption) {
|
||||
if (option.paramType !== undefined) {
|
||||
return " " + getDiagnosticText(option.paramType);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function makePadding(paddingLength: number): string {
|
||||
return Array(paddingLength + 1).join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
function executeCommandLineWorker(
|
||||
sys: System,
|
||||
cb: ExecuteCommandLineCallbacks | undefined,
|
||||
commandLine: ParsedCommandLine,
|
||||
) {
|
||||
let reportDiagnostic = createDiagnosticReporter(sys);
|
||||
if (commandLine.options.build) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_build_must_be_the_first_command_line_argument));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
// Configuration file name (if any)
|
||||
let configFileName: string | undefined;
|
||||
if (commandLine.options.locale) {
|
||||
validateLocaleAndSetLanguage(commandLine.options.locale, sys, commandLine.errors);
|
||||
}
|
||||
|
||||
// If there are any errors due to command line parsing and/or
|
||||
// setting up localization, report them and quit.
|
||||
if (commandLine.errors.length > 0) {
|
||||
commandLine.errors.forEach(reportDiagnostic);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
if (commandLine.options.init) {
|
||||
writeConfigFile(sys, reportDiagnostic, commandLine.options, commandLine.fileNames);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (commandLine.options.version) {
|
||||
printVersion(sys);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (commandLine.options.help || commandLine.options.all) {
|
||||
printVersion(sys);
|
||||
printHelp(sys, getOptionsForHelp(commandLine));
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (commandLine.options.project) {
|
||||
if (commandLine.fileNames.length !== 0) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
const fileOrDirectory = normalizePath(commandLine.options.project);
|
||||
if (!fileOrDirectory /* current directory "." */ || sys.directoryExists(fileOrDirectory)) {
|
||||
configFileName = combinePaths(fileOrDirectory, "tsconfig.json");
|
||||
if (!sys.fileExists(configFileName)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
}
|
||||
else {
|
||||
configFileName = fileOrDirectory;
|
||||
if (!sys.fileExists(configFileName)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (commandLine.fileNames.length === 0) {
|
||||
const searchPath = normalizePath(sys.getCurrentDirectory());
|
||||
configFileName = findConfigFile(searchPath, sys.fileExists);
|
||||
}
|
||||
|
||||
if (commandLine.fileNames.length === 0 && !configFileName) {
|
||||
printVersion(sys);
|
||||
printHelp(sys, getOptionsForHelp(commandLine));
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
const currentDirectory = sys.getCurrentDirectory();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(sys.useCaseSensitiveFileNames);
|
||||
const commandLineOptions = convertToOptionsWithAbsolutePaths(
|
||||
commandLine.options,
|
||||
fileName => toPath(fileName, currentDirectory, getCanonicalFileName)
|
||||
);
|
||||
if (configFileName) {
|
||||
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic)!; // TODO: GH#18217
|
||||
if (commandLineOptions.showConfig) {
|
||||
if (configParseResult.errors.length !== 0) {
|
||||
reportDiagnostic = updateReportDiagnostic(
|
||||
sys,
|
||||
reportDiagnostic,
|
||||
configParseResult.options
|
||||
);
|
||||
configParseResult.errors.forEach(reportDiagnostic);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
sys.write(JSON.stringify(convertToTSConfig(configParseResult, configFileName, sys), null, 4) + sys.newLine);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
reportDiagnostic = updateReportDiagnostic(
|
||||
sys,
|
||||
reportDiagnostic,
|
||||
configParseResult.options
|
||||
);
|
||||
if (isWatchSet(configParseResult.options)) {
|
||||
if (reportWatchModeWithoutSysSupport(sys, reportDiagnostic)) return;
|
||||
createWatchOfConfigFile(
|
||||
sys,
|
||||
reportDiagnostic,
|
||||
configParseResult,
|
||||
commandLineOptions
|
||||
);
|
||||
}
|
||||
else if (isIncrementalCompilation(configParseResult.options)) {
|
||||
performIncrementalCompilation(
|
||||
sys,
|
||||
reportDiagnostic,
|
||||
cb,
|
||||
configParseResult
|
||||
);
|
||||
}
|
||||
else {
|
||||
performCompilation(
|
||||
sys,
|
||||
reportDiagnostic,
|
||||
cb,
|
||||
configParseResult
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (commandLineOptions.showConfig) {
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
sys.write(JSON.stringify(convertToTSConfig(commandLine, combinePaths(currentDirectory, "tsconfig.json"), sys), null, 4) + sys.newLine);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
reportDiagnostic = updateReportDiagnostic(
|
||||
sys,
|
||||
reportDiagnostic,
|
||||
commandLineOptions
|
||||
);
|
||||
if (isWatchSet(commandLineOptions)) {
|
||||
if (reportWatchModeWithoutSysSupport(sys, reportDiagnostic)) return;
|
||||
createWatchOfFilesAndCompilerOptions(
|
||||
sys,
|
||||
reportDiagnostic,
|
||||
commandLine.fileNames,
|
||||
commandLineOptions
|
||||
);
|
||||
}
|
||||
else if (isIncrementalCompilation(commandLineOptions)) {
|
||||
performIncrementalCompilation(
|
||||
sys,
|
||||
reportDiagnostic,
|
||||
cb,
|
||||
{ ...commandLine, options: commandLineOptions }
|
||||
);
|
||||
}
|
||||
else {
|
||||
performCompilation(
|
||||
sys,
|
||||
reportDiagnostic,
|
||||
cb,
|
||||
{ ...commandLine, options: commandLineOptions }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function isBuild(commandLineArgs: readonly string[]) {
|
||||
if (commandLineArgs.length > 0 && commandLineArgs[0].charCodeAt(0) === CharacterCodes.minus) {
|
||||
const firstOption = commandLineArgs[0].slice(commandLineArgs[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
|
||||
return firstOption === "build" || firstOption === "b";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export interface ExecuteCommandLineCallbacks {
|
||||
onCompilerHostCreate: (host: CompilerHost) => void;
|
||||
onCompilationComplete: (config: ParsedCommandLine) => void;
|
||||
onSolutionBuilderHostCreate: (host: SolutionBuilderHost<BuilderProgram> | SolutionBuilderWithWatchHost<BuilderProgram>) => void;
|
||||
onSolutionBuildComplete: (configs: readonly ParsedCommandLine[]) => void;
|
||||
}
|
||||
export function executeCommandLine(
|
||||
system: System,
|
||||
cb: ExecuteCommandLineCallbacks,
|
||||
commandLineArgs: readonly string[],
|
||||
): void {
|
||||
if (isBuild(commandLineArgs)) {
|
||||
return performBuild(
|
||||
system,
|
||||
cb,
|
||||
commandLineArgs.slice(1)
|
||||
);
|
||||
}
|
||||
|
||||
const commandLine = parseCommandLine(commandLineArgs, path => system.readFile(path));
|
||||
if (commandLine.options.generateCpuProfile && system.enableCPUProfiler) {
|
||||
system.enableCPUProfiler(commandLine.options.generateCpuProfile, () => executeCommandLineWorker(
|
||||
system,
|
||||
cb,
|
||||
commandLine
|
||||
));
|
||||
}
|
||||
else {
|
||||
executeCommandLineWorker(system, cb, commandLine);
|
||||
}
|
||||
}
|
||||
|
||||
function reportWatchModeWithoutSysSupport(sys: System, reportDiagnostic: DiagnosticReporter) {
|
||||
if (!sys.watchFile || !sys.watchDirectory) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));
|
||||
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function performBuildWorker(
|
||||
sys: System,
|
||||
cb: ExecuteCommandLineCallbacks | undefined,
|
||||
buildOptions: BuildOptions,
|
||||
projects: string[],
|
||||
errors: Diagnostic[]
|
||||
) {
|
||||
// Update to pretty if host supports it
|
||||
const reportDiagnostic = updateReportDiagnostic(
|
||||
sys,
|
||||
createDiagnosticReporter(sys),
|
||||
buildOptions
|
||||
);
|
||||
|
||||
if (buildOptions.locale) {
|
||||
validateLocaleAndSetLanguage(buildOptions.locale, sys, errors);
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
errors.forEach(reportDiagnostic);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
if (buildOptions.help) {
|
||||
printVersion(sys);
|
||||
printHelp(sys, buildOpts, "--build ");
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (projects.length === 0) {
|
||||
printVersion(sys);
|
||||
printHelp(sys, buildOpts, "--build ");
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (!sys.getModifiedTime || !sys.setModifiedTime || (buildOptions.clean && !sys.deleteFile)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build"));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
if (buildOptions.watch) {
|
||||
if (reportWatchModeWithoutSysSupport(sys, reportDiagnostic)) return;
|
||||
const buildHost = createSolutionBuilderWithWatchHost(
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
reportDiagnostic,
|
||||
createBuilderStatusReporter(sys, shouldBePretty(sys, buildOptions)),
|
||||
createWatchStatusReporter(sys, buildOptions)
|
||||
);
|
||||
if (cb && cb.onSolutionBuilderHostCreate) cb.onSolutionBuilderHostCreate(buildHost);
|
||||
updateCreateProgram(sys, buildHost);
|
||||
buildHost.afterProgramEmitAndDiagnostics = program => reportStatistics(sys, program.getProgram());
|
||||
const builder = createSolutionBuilderWithWatch(buildHost, projects, buildOptions);
|
||||
builder.build();
|
||||
return;
|
||||
}
|
||||
|
||||
const buildHost = createSolutionBuilderHost(
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
reportDiagnostic,
|
||||
createBuilderStatusReporter(sys, shouldBePretty(sys, buildOptions)),
|
||||
createReportErrorSummary(sys, buildOptions)
|
||||
);
|
||||
if (cb && cb.onSolutionBuilderHostCreate) cb.onSolutionBuilderHostCreate(buildHost);
|
||||
updateCreateProgram(sys, buildHost);
|
||||
buildHost.afterProgramEmitAndDiagnostics = program => reportStatistics(sys, program.getProgram());
|
||||
const builder = createSolutionBuilder(buildHost, projects, buildOptions);
|
||||
const exitStatus = buildOptions.clean ? builder.clean() : builder.build();
|
||||
if (cb && cb.onSolutionBuildComplete) cb.onSolutionBuildComplete(builder.getAllParsedConfigs());
|
||||
return sys.exit(exitStatus);
|
||||
}
|
||||
|
||||
function performBuild(
|
||||
sys: System,
|
||||
cb: ExecuteCommandLineCallbacks | undefined,
|
||||
args: readonly string[]
|
||||
) {
|
||||
const { buildOptions, projects, errors } = parseBuildCommand(args);
|
||||
if (buildOptions.generateCpuProfile && sys.enableCPUProfiler) {
|
||||
sys.enableCPUProfiler(buildOptions.generateCpuProfile, () => performBuildWorker(
|
||||
sys,
|
||||
cb,
|
||||
buildOptions,
|
||||
projects,
|
||||
errors
|
||||
));
|
||||
}
|
||||
else {
|
||||
performBuildWorker(
|
||||
sys,
|
||||
cb,
|
||||
buildOptions,
|
||||
projects,
|
||||
errors
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function createReportErrorSummary(sys: System, options: CompilerOptions | BuildOptions): ReportEmitErrorSummary | undefined {
|
||||
return shouldBePretty(sys, options) ?
|
||||
errorCount => sys.write(getErrorSummaryText(errorCount, sys.newLine)) :
|
||||
undefined;
|
||||
}
|
||||
|
||||
function performCompilation(
|
||||
sys: System,
|
||||
reportDiagnostic: DiagnosticReporter,
|
||||
cb: ExecuteCommandLineCallbacks | undefined,
|
||||
config: ParsedCommandLine
|
||||
) {
|
||||
const { fileNames, options, projectReferences } = config;
|
||||
const host = createCompilerHostWorker(options, /*setParentPos*/ undefined, sys);
|
||||
if (cb && cb.onCompilerHostCreate) cb.onCompilerHostCreate(host);
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
|
||||
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName));
|
||||
enableStatistics(sys, options);
|
||||
|
||||
const programOptions: CreateProgramOptions = {
|
||||
rootNames: fileNames,
|
||||
options,
|
||||
projectReferences,
|
||||
host,
|
||||
configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config)
|
||||
};
|
||||
const program = createProgram(programOptions);
|
||||
const exitStatus = emitFilesAndReportErrorsAndGetExitStatus(
|
||||
program,
|
||||
reportDiagnostic,
|
||||
s => sys.write(s + sys.newLine),
|
||||
createReportErrorSummary(sys, options)
|
||||
);
|
||||
reportStatistics(sys, program);
|
||||
if (cb && cb.onCompilationComplete) cb.onCompilationComplete(config);
|
||||
return sys.exit(exitStatus);
|
||||
}
|
||||
|
||||
function performIncrementalCompilation(
|
||||
sys: System,
|
||||
reportDiagnostic: DiagnosticReporter,
|
||||
cb: ExecuteCommandLineCallbacks | undefined,
|
||||
config: ParsedCommandLine
|
||||
) {
|
||||
const { options, fileNames, projectReferences } = config;
|
||||
enableStatistics(sys, options);
|
||||
const host = createIncrementalCompilerHost(options, sys);
|
||||
if (cb && cb.onCompilerHostCreate) cb.onCompilerHostCreate(host);
|
||||
const exitStatus = ts.performIncrementalCompilation({
|
||||
host,
|
||||
system: sys,
|
||||
rootNames: fileNames,
|
||||
options,
|
||||
configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config),
|
||||
projectReferences,
|
||||
reportDiagnostic,
|
||||
reportErrorSummary: createReportErrorSummary(sys, options),
|
||||
afterProgramEmitAndDiagnostics: builderProgram => reportStatistics(sys, builderProgram.getProgram())
|
||||
});
|
||||
if (cb && cb.onCompilationComplete) cb.onCompilationComplete(config);
|
||||
return sys.exit(exitStatus);
|
||||
}
|
||||
|
||||
function updateCreateProgram<T extends BuilderProgram>(sys: System, host: { createProgram: CreateProgram<T>; }) {
|
||||
const compileUsingBuilder = host.createProgram;
|
||||
host.createProgram = (rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences) => {
|
||||
Debug.assert(rootNames !== undefined || (options === undefined && !!oldProgram));
|
||||
if (options !== undefined) {
|
||||
enableStatistics(sys, options);
|
||||
}
|
||||
return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
};
|
||||
}
|
||||
|
||||
function updateWatchCompilationHost(sys: System, watchCompilerHost: WatchCompilerHost<EmitAndSemanticDiagnosticsBuilderProgram>) {
|
||||
updateCreateProgram(sys, watchCompilerHost);
|
||||
const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217
|
||||
watchCompilerHost.afterProgramCreate = builderProgram => {
|
||||
emitFilesUsingBuilder(builderProgram);
|
||||
reportStatistics(sys, builderProgram.getProgram());
|
||||
};
|
||||
}
|
||||
|
||||
function createWatchStatusReporter(sys: System, options: CompilerOptions | BuildOptions) {
|
||||
return ts.createWatchStatusReporter(sys, shouldBePretty(sys, options));
|
||||
}
|
||||
|
||||
function createWatchOfConfigFile(
|
||||
sys: System,
|
||||
reportDiagnostic: DiagnosticReporter,
|
||||
configParseResult: ParsedCommandLine,
|
||||
optionsToExtend: CompilerOptions
|
||||
) {
|
||||
const watchCompilerHost = createWatchCompilerHostOfConfigFile(
|
||||
configParseResult.options.configFilePath!,
|
||||
optionsToExtend,
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
reportDiagnostic,
|
||||
createWatchStatusReporter(sys, configParseResult.options)
|
||||
); // TODO: GH#18217
|
||||
updateWatchCompilationHost(sys, watchCompilerHost);
|
||||
watchCompilerHost.configFileParsingResult = configParseResult;
|
||||
createWatchProgram(watchCompilerHost);
|
||||
}
|
||||
|
||||
function createWatchOfFilesAndCompilerOptions(
|
||||
sys: System,
|
||||
reportDiagnostic: DiagnosticReporter,
|
||||
rootFiles: string[],
|
||||
options: CompilerOptions
|
||||
) {
|
||||
const watchCompilerHost = createWatchCompilerHostOfFilesAndCompilerOptions(
|
||||
rootFiles,
|
||||
options,
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
reportDiagnostic,
|
||||
createWatchStatusReporter(sys, options)
|
||||
);
|
||||
updateWatchCompilationHost(sys, watchCompilerHost);
|
||||
createWatchProgram(watchCompilerHost);
|
||||
}
|
||||
|
||||
function canReportDiagnostics(sys: System, compilerOptions: CompilerOptions) {
|
||||
return sys === ts.sys && (compilerOptions.diagnostics || compilerOptions.extendedDiagnostics);
|
||||
}
|
||||
|
||||
function enableStatistics(sys: System, compilerOptions: CompilerOptions) {
|
||||
if (canReportDiagnostics(sys, compilerOptions)) {
|
||||
performance.enable();
|
||||
}
|
||||
}
|
||||
|
||||
function reportStatistics(sys: System, program: Program) {
|
||||
let statistics: Statistic[];
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
if (canReportDiagnostics(sys, compilerOptions)) {
|
||||
statistics = [];
|
||||
const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
|
||||
reportCountStatistic("Files", program.getSourceFiles().length);
|
||||
reportCountStatistic("Lines", countLines(program));
|
||||
reportCountStatistic("Nodes", program.getNodeCount());
|
||||
reportCountStatistic("Identifiers", program.getIdentifierCount());
|
||||
reportCountStatistic("Symbols", program.getSymbolCount());
|
||||
reportCountStatistic("Types", program.getTypeCount());
|
||||
|
||||
if (memoryUsed >= 0) {
|
||||
reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K");
|
||||
}
|
||||
|
||||
const programTime = performance.getDuration("Program");
|
||||
const bindTime = performance.getDuration("Bind");
|
||||
const checkTime = performance.getDuration("Check");
|
||||
const emitTime = performance.getDuration("Emit");
|
||||
if (compilerOptions.extendedDiagnostics) {
|
||||
const caches = program.getRelationCacheSizes();
|
||||
reportCountStatistic("Assignability cache size", caches.assignable);
|
||||
reportCountStatistic("Identity cache size", caches.identity);
|
||||
reportCountStatistic("Subtype cache size", caches.subtype);
|
||||
performance.forEachMeasure((name, duration) => reportTimeStatistic(`${name} time`, duration));
|
||||
}
|
||||
else {
|
||||
// Individual component times.
|
||||
// Note: To match the behavior of previous versions of the compiler, the reported parse time includes
|
||||
// I/O read time and processing time for triple-slash references and module imports, and the reported
|
||||
// emit time includes I/O write time. We preserve this behavior so we can accurately compare times.
|
||||
reportTimeStatistic("I/O read", performance.getDuration("I/O Read"));
|
||||
reportTimeStatistic("I/O write", performance.getDuration("I/O Write"));
|
||||
reportTimeStatistic("Parse time", programTime);
|
||||
reportTimeStatistic("Bind time", bindTime);
|
||||
reportTimeStatistic("Check time", checkTime);
|
||||
reportTimeStatistic("Emit time", emitTime);
|
||||
}
|
||||
reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime);
|
||||
reportStatistics();
|
||||
|
||||
performance.disable();
|
||||
}
|
||||
|
||||
function reportStatistics() {
|
||||
let nameSize = 0;
|
||||
let valueSize = 0;
|
||||
for (const { name, value } of statistics) {
|
||||
if (name.length > nameSize) {
|
||||
nameSize = name.length;
|
||||
}
|
||||
|
||||
if (value.length > valueSize) {
|
||||
valueSize = value.length;
|
||||
}
|
||||
}
|
||||
|
||||
for (const { name, value } of statistics) {
|
||||
sys.write(padRight(name + ":", nameSize + 2) + padLeft(value.toString(), valueSize) + sys.newLine);
|
||||
}
|
||||
}
|
||||
|
||||
function reportStatisticalValue(name: string, value: string) {
|
||||
statistics.push({ name, value });
|
||||
}
|
||||
|
||||
function reportCountStatistic(name: string, count: number) {
|
||||
reportStatisticalValue(name, "" + count);
|
||||
}
|
||||
|
||||
function reportTimeStatistic(name: string, time: number) {
|
||||
reportStatisticalValue(name, (time / 1000).toFixed(2) + "s");
|
||||
}
|
||||
}
|
||||
|
||||
function writeConfigFile(
|
||||
sys: System,
|
||||
reportDiagnostic: DiagnosticReporter,
|
||||
options: CompilerOptions,
|
||||
fileNames: string[]
|
||||
) {
|
||||
const currentDirectory = sys.getCurrentDirectory();
|
||||
const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
|
||||
if (sys.fileExists(file)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file));
|
||||
}
|
||||
else {
|
||||
sys.writeFile(file, generateTSConfig(options, fileNames, sys.newLine));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ts.Debug.isDebugging) {
|
||||
ts.Debug.enableDebugInfo();
|
||||
}
|
||||
|
||||
if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
|
||||
ts.sys.tryEnableSourceMapsForHost();
|
||||
}
|
||||
|
||||
if (ts.sys.setBlocking) {
|
||||
ts.sys.setBlocking();
|
||||
}
|
||||
461
src/tsc/tsc.ts
461
src/tsc/tsc.ts
@@ -1,450 +1,11 @@
|
||||
namespace ts {
|
||||
interface Statistic {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
function countLines(program: Program): number {
|
||||
let count = 0;
|
||||
forEach(program.getSourceFiles(), file => {
|
||||
count += getLineStarts(file).length;
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
let reportDiagnostic = createDiagnosticReporter(sys);
|
||||
function updateReportDiagnostic(options: CompilerOptions | BuildOptions) {
|
||||
if (shouldBePretty(options)) {
|
||||
reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
function defaultIsPretty() {
|
||||
return !!sys.writeOutputIsTTY && sys.writeOutputIsTTY();
|
||||
}
|
||||
|
||||
function shouldBePretty(options: CompilerOptions | BuildOptions) {
|
||||
if (!options || typeof options.pretty === "undefined") {
|
||||
return defaultIsPretty();
|
||||
}
|
||||
return options.pretty;
|
||||
}
|
||||
|
||||
function padLeft(s: string, length: number) {
|
||||
while (s.length < length) {
|
||||
s = " " + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function padRight(s: string, length: number) {
|
||||
while (s.length < length) {
|
||||
s = s + " ";
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function getOptionsForHelp(commandLine: ParsedCommandLine) {
|
||||
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
|
||||
return !!commandLine.options.all ?
|
||||
sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) :
|
||||
filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView);
|
||||
}
|
||||
|
||||
function executeCommandLineWorker(commandLine: ParsedCommandLine) {
|
||||
if (commandLine.options.build) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_build_must_be_the_first_command_line_argument));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
// Configuration file name (if any)
|
||||
let configFileName: string | undefined;
|
||||
if (commandLine.options.locale) {
|
||||
validateLocaleAndSetLanguage(commandLine.options.locale, sys, commandLine.errors);
|
||||
}
|
||||
|
||||
// If there are any errors due to command line parsing and/or
|
||||
// setting up localization, report them and quit.
|
||||
if (commandLine.errors.length > 0) {
|
||||
commandLine.errors.forEach(reportDiagnostic);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
if (commandLine.options.init) {
|
||||
writeConfigFile(commandLine.options, commandLine.fileNames);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (commandLine.options.version) {
|
||||
printVersion();
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (commandLine.options.help || commandLine.options.all) {
|
||||
printVersion();
|
||||
printHelp(getOptionsForHelp(commandLine));
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (commandLine.options.project) {
|
||||
if (commandLine.fileNames.length !== 0) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
const fileOrDirectory = normalizePath(commandLine.options.project);
|
||||
if (!fileOrDirectory /* current directory "." */ || sys.directoryExists(fileOrDirectory)) {
|
||||
configFileName = combinePaths(fileOrDirectory, "tsconfig.json");
|
||||
if (!sys.fileExists(configFileName)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
}
|
||||
else {
|
||||
configFileName = fileOrDirectory;
|
||||
if (!sys.fileExists(configFileName)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (commandLine.fileNames.length === 0) {
|
||||
const searchPath = normalizePath(sys.getCurrentDirectory());
|
||||
configFileName = findConfigFile(searchPath, sys.fileExists);
|
||||
}
|
||||
|
||||
if (commandLine.fileNames.length === 0 && !configFileName) {
|
||||
printVersion();
|
||||
printHelp(getOptionsForHelp(commandLine));
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
const currentDirectory = sys.getCurrentDirectory();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(sys.useCaseSensitiveFileNames);
|
||||
const commandLineOptions = convertToOptionsWithAbsolutePaths(
|
||||
commandLine.options,
|
||||
fileName => toPath(fileName, currentDirectory, getCanonicalFileName)
|
||||
);
|
||||
if (configFileName) {
|
||||
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic)!; // TODO: GH#18217
|
||||
if (commandLineOptions.showConfig) {
|
||||
if (configParseResult.errors.length !== 0) {
|
||||
updateReportDiagnostic(configParseResult.options);
|
||||
configParseResult.errors.forEach(reportDiagnostic);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
sys.write(JSON.stringify(convertToTSConfig(configParseResult, configFileName, sys), null, 4) + sys.newLine);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
updateReportDiagnostic(configParseResult.options);
|
||||
if (isWatchSet(configParseResult.options)) {
|
||||
reportWatchModeWithoutSysSupport();
|
||||
createWatchOfConfigFile(configParseResult, commandLineOptions);
|
||||
}
|
||||
else if (isIncrementalCompilation(configParseResult.options)) {
|
||||
performIncrementalCompilation(configParseResult);
|
||||
}
|
||||
else {
|
||||
performCompilation(configParseResult.fileNames, configParseResult.projectReferences, configParseResult.options, getConfigFileParsingDiagnostics(configParseResult));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (commandLineOptions.showConfig) {
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
sys.write(JSON.stringify(convertToTSConfig(commandLine, combinePaths(currentDirectory, "tsconfig.json"), sys), null, 4) + sys.newLine);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
updateReportDiagnostic(commandLineOptions);
|
||||
if (isWatchSet(commandLineOptions)) {
|
||||
reportWatchModeWithoutSysSupport();
|
||||
createWatchOfFilesAndCompilerOptions(commandLine.fileNames, commandLineOptions);
|
||||
}
|
||||
else if (isIncrementalCompilation(commandLineOptions)) {
|
||||
performIncrementalCompilation({
|
||||
...commandLine,
|
||||
options: commandLineOptions
|
||||
});
|
||||
}
|
||||
else {
|
||||
performCompilation(commandLine.fileNames, /*references*/ undefined, commandLineOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function executeCommandLine(args: string[]): void {
|
||||
if (args.length > 0 && args[0].charCodeAt(0) === CharacterCodes.minus) {
|
||||
const firstOption = args[0].slice(args[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
|
||||
if (firstOption === "build" || firstOption === "b") {
|
||||
return performBuild(args.slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
const commandLine = parseCommandLine(args);
|
||||
|
||||
if (commandLine.options.generateCpuProfile && sys.enableCPUProfiler) {
|
||||
sys.enableCPUProfiler(commandLine.options.generateCpuProfile, () => executeCommandLineWorker(commandLine));
|
||||
}
|
||||
else {
|
||||
executeCommandLineWorker(commandLine);
|
||||
}
|
||||
}
|
||||
|
||||
function reportWatchModeWithoutSysSupport() {
|
||||
if (!sys.watchFile || !sys.watchDirectory) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));
|
||||
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
}
|
||||
|
||||
function performBuildWorker(buildOptions: BuildOptions, projects: string[], errors: Diagnostic[]) {
|
||||
// Update to pretty if host supports it
|
||||
updateReportDiagnostic(buildOptions);
|
||||
|
||||
if (buildOptions.locale) {
|
||||
validateLocaleAndSetLanguage(buildOptions.locale, sys, errors);
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
errors.forEach(reportDiagnostic);
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
if (buildOptions.help) {
|
||||
printVersion();
|
||||
printHelp(buildOpts, "--build ");
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (projects.length === 0) {
|
||||
printVersion();
|
||||
printHelp(buildOpts, "--build ");
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (!sys.getModifiedTime || !sys.setModifiedTime || (buildOptions.clean && !sys.deleteFile)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build"));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
if (buildOptions.watch) {
|
||||
reportWatchModeWithoutSysSupport();
|
||||
const buildHost = createSolutionBuilderWithWatchHost(sys, /*createProgram*/ undefined, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty(buildOptions)), createWatchStatusReporter(buildOptions));
|
||||
updateCreateProgram(buildHost);
|
||||
buildHost.afterProgramEmitAndDiagnostics = program => reportStatistics(program.getProgram());
|
||||
const builder = createSolutionBuilderWithWatch(buildHost, projects, buildOptions);
|
||||
builder.build();
|
||||
return;
|
||||
}
|
||||
|
||||
const buildHost = createSolutionBuilderHost(sys, /*createProgram*/ undefined, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty(buildOptions)), createReportErrorSummary(buildOptions));
|
||||
updateCreateProgram(buildHost);
|
||||
buildHost.afterProgramEmitAndDiagnostics = program => reportStatistics(program.getProgram());
|
||||
const builder = createSolutionBuilder(buildHost, projects, buildOptions);
|
||||
return sys.exit(buildOptions.clean ? builder.clean() : builder.build());
|
||||
}
|
||||
|
||||
function performBuild(args: string[]) {
|
||||
const { buildOptions, projects, errors } = parseBuildCommand(args);
|
||||
if (buildOptions.generateCpuProfile && sys.enableCPUProfiler) {
|
||||
sys.enableCPUProfiler(buildOptions.generateCpuProfile, () => performBuildWorker(buildOptions, projects, errors));
|
||||
}
|
||||
else {
|
||||
performBuildWorker(buildOptions, projects, errors);
|
||||
}
|
||||
}
|
||||
|
||||
function createReportErrorSummary(options: CompilerOptions | BuildOptions): ReportEmitErrorSummary | undefined {
|
||||
return shouldBePretty(options) ?
|
||||
errorCount => sys.write(getErrorSummaryText(errorCount, sys.newLine)) :
|
||||
undefined;
|
||||
}
|
||||
|
||||
function performCompilation(rootNames: string[], projectReferences: readonly ProjectReference[] | undefined, options: CompilerOptions, configFileParsingDiagnostics?: readonly Diagnostic[]) {
|
||||
const host = createCompilerHost(options);
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
|
||||
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName));
|
||||
enableStatistics(options);
|
||||
|
||||
const programOptions: CreateProgramOptions = {
|
||||
rootNames,
|
||||
options,
|
||||
projectReferences,
|
||||
host,
|
||||
configFileParsingDiagnostics
|
||||
};
|
||||
const program = createProgram(programOptions);
|
||||
const exitStatus = emitFilesAndReportErrorsAndGetExitStatus(
|
||||
program,
|
||||
reportDiagnostic,
|
||||
s => sys.write(s + sys.newLine),
|
||||
createReportErrorSummary(options)
|
||||
);
|
||||
reportStatistics(program);
|
||||
return sys.exit(exitStatus);
|
||||
}
|
||||
|
||||
function performIncrementalCompilation(config: ParsedCommandLine) {
|
||||
const { options, fileNames, projectReferences } = config;
|
||||
enableStatistics(options);
|
||||
return sys.exit(ts.performIncrementalCompilation({
|
||||
rootNames: fileNames,
|
||||
options,
|
||||
configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config),
|
||||
projectReferences,
|
||||
reportDiagnostic,
|
||||
reportErrorSummary: createReportErrorSummary(options),
|
||||
afterProgramEmitAndDiagnostics: builderProgram => reportStatistics(builderProgram.getProgram())
|
||||
}));
|
||||
}
|
||||
|
||||
function updateCreateProgram<T extends BuilderProgram>(host: { createProgram: CreateProgram<T>; }) {
|
||||
const compileUsingBuilder = host.createProgram;
|
||||
host.createProgram = (rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences) => {
|
||||
Debug.assert(rootNames !== undefined || (options === undefined && !!oldProgram));
|
||||
if (options !== undefined) {
|
||||
enableStatistics(options);
|
||||
}
|
||||
return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
};
|
||||
}
|
||||
|
||||
function updateWatchCompilationHost(watchCompilerHost: WatchCompilerHost<EmitAndSemanticDiagnosticsBuilderProgram>) {
|
||||
updateCreateProgram(watchCompilerHost);
|
||||
const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217
|
||||
watchCompilerHost.afterProgramCreate = builderProgram => {
|
||||
emitFilesUsingBuilder(builderProgram);
|
||||
reportStatistics(builderProgram.getProgram());
|
||||
};
|
||||
}
|
||||
|
||||
function createWatchStatusReporter(options: CompilerOptions | BuildOptions) {
|
||||
return ts.createWatchStatusReporter(sys, shouldBePretty(options));
|
||||
}
|
||||
|
||||
function createWatchOfConfigFile(configParseResult: ParsedCommandLine, optionsToExtend: CompilerOptions) {
|
||||
const watchCompilerHost = createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath!, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options)); // TODO: GH#18217
|
||||
updateWatchCompilationHost(watchCompilerHost);
|
||||
watchCompilerHost.configFileParsingResult = configParseResult;
|
||||
createWatchProgram(watchCompilerHost);
|
||||
}
|
||||
|
||||
function createWatchOfFilesAndCompilerOptions(rootFiles: string[], options: CompilerOptions) {
|
||||
const watchCompilerHost = createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(options));
|
||||
updateWatchCompilationHost(watchCompilerHost);
|
||||
createWatchProgram(watchCompilerHost);
|
||||
}
|
||||
|
||||
function enableStatistics(compilerOptions: CompilerOptions) {
|
||||
if (compilerOptions.diagnostics || compilerOptions.extendedDiagnostics) {
|
||||
performance.enable();
|
||||
}
|
||||
}
|
||||
|
||||
function reportStatistics(program: Program) {
|
||||
let statistics: Statistic[];
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
if (compilerOptions.diagnostics || compilerOptions.extendedDiagnostics) {
|
||||
statistics = [];
|
||||
const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
|
||||
reportCountStatistic("Files", program.getSourceFiles().length);
|
||||
reportCountStatistic("Lines", countLines(program));
|
||||
reportCountStatistic("Nodes", program.getNodeCount());
|
||||
reportCountStatistic("Identifiers", program.getIdentifierCount());
|
||||
reportCountStatistic("Symbols", program.getSymbolCount());
|
||||
reportCountStatistic("Types", program.getTypeCount());
|
||||
|
||||
if (memoryUsed >= 0) {
|
||||
reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K");
|
||||
}
|
||||
|
||||
const programTime = performance.getDuration("Program");
|
||||
const bindTime = performance.getDuration("Bind");
|
||||
const checkTime = performance.getDuration("Check");
|
||||
const emitTime = performance.getDuration("Emit");
|
||||
if (compilerOptions.extendedDiagnostics) {
|
||||
const caches = program.getRelationCacheSizes();
|
||||
reportCountStatistic("Assignability cache size", caches.assignable);
|
||||
reportCountStatistic("Identity cache size", caches.identity);
|
||||
reportCountStatistic("Subtype cache size", caches.subtype);
|
||||
performance.forEachMeasure((name, duration) => reportTimeStatistic(`${name} time`, duration));
|
||||
}
|
||||
else {
|
||||
// Individual component times.
|
||||
// Note: To match the behavior of previous versions of the compiler, the reported parse time includes
|
||||
// I/O read time and processing time for triple-slash references and module imports, and the reported
|
||||
// emit time includes I/O write time. We preserve this behavior so we can accurately compare times.
|
||||
reportTimeStatistic("I/O read", performance.getDuration("I/O Read"));
|
||||
reportTimeStatistic("I/O write", performance.getDuration("I/O Write"));
|
||||
reportTimeStatistic("Parse time", programTime);
|
||||
reportTimeStatistic("Bind time", bindTime);
|
||||
reportTimeStatistic("Check time", checkTime);
|
||||
reportTimeStatistic("Emit time", emitTime);
|
||||
}
|
||||
reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime);
|
||||
reportStatistics();
|
||||
|
||||
performance.disable();
|
||||
}
|
||||
|
||||
function reportStatistics() {
|
||||
let nameSize = 0;
|
||||
let valueSize = 0;
|
||||
for (const { name, value } of statistics) {
|
||||
if (name.length > nameSize) {
|
||||
nameSize = name.length;
|
||||
}
|
||||
|
||||
if (value.length > valueSize) {
|
||||
valueSize = value.length;
|
||||
}
|
||||
}
|
||||
|
||||
for (const { name, value } of statistics) {
|
||||
sys.write(padRight(name + ":", nameSize + 2) + padLeft(value.toString(), valueSize) + sys.newLine);
|
||||
}
|
||||
}
|
||||
|
||||
function reportStatisticalValue(name: string, value: string) {
|
||||
statistics.push({ name, value });
|
||||
}
|
||||
|
||||
function reportCountStatistic(name: string, count: number) {
|
||||
reportStatisticalValue(name, "" + count);
|
||||
}
|
||||
|
||||
function reportTimeStatistic(name: string, time: number) {
|
||||
reportStatisticalValue(name, (time / 1000).toFixed(2) + "s");
|
||||
}
|
||||
}
|
||||
|
||||
function writeConfigFile(options: CompilerOptions, fileNames: string[]) {
|
||||
const currentDirectory = sys.getCurrentDirectory();
|
||||
const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
|
||||
if (sys.fileExists(file)) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file));
|
||||
}
|
||||
else {
|
||||
sys.writeFile(file, generateTSConfig(options, fileNames, sys.newLine));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ts.Debug.isDebugging) {
|
||||
ts.Debug.enableDebugInfo();
|
||||
}
|
||||
|
||||
if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
|
||||
ts.sys.tryEnableSourceMapsForHost();
|
||||
}
|
||||
|
||||
if (ts.sys.setBlocking) {
|
||||
ts.sys.setBlocking();
|
||||
}
|
||||
|
||||
ts.executeCommandLine(ts.sys.args);
|
||||
// This file actually uses arguments passed on commandline and executes it
|
||||
ts.executeCommandLine(
|
||||
ts.sys,
|
||||
{
|
||||
onCompilerHostCreate: ts.noop,
|
||||
onCompilationComplete: ts.noop,
|
||||
onSolutionBuilderHostCreate: ts.noop,
|
||||
onSolutionBuildComplete: ts.noop
|
||||
},
|
||||
ts.sys.args
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"outFile": "../../built/local/tsc.js"
|
||||
},
|
||||
"files": [
|
||||
"executeCommandLine.ts",
|
||||
"tsc.ts"
|
||||
],
|
||||
"references": [
|
||||
|
||||
Reference in New Issue
Block a user