mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-16 07:13:45 -05:00
Move executeCommandLine.ts into its own project (#35595)
* Move executeCommandLine.ts into its own project * Remove incorrect prepend
This commit is contained in:
729
src/executeCommandLine/executeCommandLine.ts
Normal file
729
src/executeCommandLine/executeCommandLine.ts
Normal file
@@ -0,0 +1,729 @@
|
||||
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.watch && commandLine.options.listFilesOnly) {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "listFilesOnly"));
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
|
||||
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 commandLineOptions = convertToOptionsWithAbsolutePaths(
|
||||
commandLine.options,
|
||||
fileName => getNormalizedAbsolutePath(fileName, currentDirectory)
|
||||
);
|
||||
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(system: System, compilerOptions: CompilerOptions) {
|
||||
return system === 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();
|
||||
}
|
||||
14
src/executeCommandLine/tsconfig.json
Normal file
14
src/executeCommandLine/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "../tsconfig-base",
|
||||
"compilerOptions": {
|
||||
"outFile": "../../built/local/executeCommandLine.js"
|
||||
},
|
||||
|
||||
"references": [
|
||||
{ "path": "../compiler" }
|
||||
],
|
||||
|
||||
"files": [
|
||||
"executeCommandLine.ts"
|
||||
]
|
||||
}
|
||||
11
src/executeCommandLine/tsconfig.release.json
Normal file
11
src/executeCommandLine/tsconfig.release.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outFile": "../../built/local/executeCommandLine.release.js",
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": false
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../compiler/tsconfig.release.json" }
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user