mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-16 07:13:45 -05:00
New command line help developer experience. (#44157)
* refactor help CLI output. * fix typo and omit false condition boolean output. * fix typo * add line break * add --plugins option to basic option category. * add ts icon and remove old print help function. * better command description for --jsx. * Fix test * fix lint * Improvements to the UX * Fix tests * fix test. * add missing help out. * use environemnt variable to control test case. * fix merge issues. * No `No Category` * make getWidthOfTerminal optional. * fix test * fix review. * fix review. * Update baselines Co-authored-by: Orta <git@orta.io>
This commit is contained in:
@@ -24,7 +24,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getCountsMap() {
|
||||
const counts = createMap<number>();
|
||||
const counts = new Map<string, number>();
|
||||
counts.set("Library", 0);
|
||||
counts.set("Definitions", 0);
|
||||
counts.set("TypeScript", 0);
|
||||
@@ -89,111 +89,331 @@ namespace ts {
|
||||
sys.write(getDiagnosticText(Diagnostics.Version_0, version) + sys.newLine);
|
||||
}
|
||||
|
||||
function printHelp(sys: System, optionsList: readonly CommandLineOption[], syntaxPrefix = "") {
|
||||
const output: string[] = [];
|
||||
function createColors(sys: System) {
|
||||
const showColors = defaultIsPretty(sys);
|
||||
if (!showColors) {
|
||||
return {
|
||||
bold: (str: string) => str,
|
||||
blue: (str: string) => str,
|
||||
blueBackground: (str: string) => str,
|
||||
white: (str: string) => str
|
||||
};
|
||||
}
|
||||
|
||||
// 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);
|
||||
function bold(str: string) {
|
||||
return `\x1b[1m${str}\x1b[22m`;
|
||||
}
|
||||
function blue(str: string) {
|
||||
return `\x1b[34m${str}\x1b[39m`;
|
||||
}
|
||||
function blueBackground(str: string) {
|
||||
return `\x1b[44m${str}\x1b[49m`;
|
||||
}
|
||||
function white(str: string) {
|
||||
return `\x1b[37m${str}\x1b[39m`;
|
||||
}
|
||||
return {
|
||||
bold,
|
||||
blue,
|
||||
white,
|
||||
blueBackground
|
||||
};
|
||||
}
|
||||
|
||||
// Build up the syntactic skeleton.
|
||||
let syntax = makePadding(marginLength - syntaxLength);
|
||||
syntax += `tsc ${syntaxPrefix}[${getDiagnosticText(Diagnostics.options)}] [${getDiagnosticText(Diagnostics.file)}...]`;
|
||||
function getDisplayNameTextOfOption(option: CommandLineOption) {
|
||||
return `--${option.name}${option.shortName ? `, -${option.shortName}` : ""}`;
|
||||
}
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Syntax_Colon_0, syntax));
|
||||
output.push(sys.newLine + sys.newLine);
|
||||
function generateOptionOutput(sys: System, option: CommandLineOption, rightAlignOfLeft: number, leftAlignOfRight: number) {
|
||||
interface ValueCandidate {
|
||||
// "one or more" or "any of"
|
||||
valueType: string;
|
||||
possibleValues: string;
|
||||
}
|
||||
|
||||
// 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);
|
||||
const text: string[] = [];
|
||||
const colors = createColors(sys);
|
||||
|
||||
output.push(getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine);
|
||||
// name and description
|
||||
const name = getDisplayNameTextOfOption(option);
|
||||
|
||||
// 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[] = [];
|
||||
// value type and possible value
|
||||
const valueCandidates = getValueCandidate(option);
|
||||
const defaultValueDescription = typeof option.defaultValueDescription === "object" ? getDiagnosticText(option.defaultValueDescription) : option.defaultValueDescription;
|
||||
const terminalWidth = sys.getWidthOfTerminal?.() ?? 0;
|
||||
|
||||
const optionsDescriptionMap = new Map<string, string[]>(); // Map between option.description and list of option.type if it is a kind
|
||||
// Note: child_process might return `terminalWidth` as undefined.
|
||||
if (terminalWidth >= 60) {
|
||||
let description = "";
|
||||
if (option.description) {
|
||||
description = getDiagnosticText(option.description);
|
||||
}
|
||||
text.push(...getPrettyOutput(name, description, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ true), sys.newLine);
|
||||
if (showAdditionalInfoOutput(valueCandidates, option)) {
|
||||
if (valueCandidates) {
|
||||
text.push(...getPrettyOutput(valueCandidates.valueType, valueCandidates.possibleValues, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ false), sys.newLine);
|
||||
}
|
||||
if (defaultValueDescription) {
|
||||
text.push(...getPrettyOutput(getDiagnosticText(Diagnostics.default_Colon), defaultValueDescription, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ false), sys.newLine);
|
||||
}
|
||||
}
|
||||
text.push(sys.newLine);
|
||||
}
|
||||
else {
|
||||
text.push(colors.blue(name), sys.newLine);
|
||||
if (option.description) {
|
||||
const description = getDiagnosticText(option.description);
|
||||
text.push(description);
|
||||
}
|
||||
text.push(sys.newLine);
|
||||
if (showAdditionalInfoOutput(valueCandidates, option)) {
|
||||
if (valueCandidates) {
|
||||
text.push(`${valueCandidates.valueType} ${valueCandidates.possibleValues}`);
|
||||
}
|
||||
if (defaultValueDescription) {
|
||||
if (valueCandidates) text.push(sys.newLine);
|
||||
const diagType = getDiagnosticText(Diagnostics.default_Colon);
|
||||
text.push(`${diagType} ${defaultValueDescription}`);
|
||||
}
|
||||
|
||||
text.push(sys.newLine);
|
||||
}
|
||||
text.push(sys.newLine);
|
||||
}
|
||||
return text;
|
||||
|
||||
function showAdditionalInfoOutput(valueCandidates: ValueCandidate | undefined, option: CommandLineOption): boolean {
|
||||
const ignoreValues = ["string"];
|
||||
const ignoredDescriptions = [undefined, "false", "n/a"];
|
||||
const defaultValueDescription = option.defaultValueDescription;
|
||||
if (option.category === Diagnostics.Command_line_Options) return false;
|
||||
|
||||
if (contains(ignoreValues, valueCandidates?.possibleValues) && contains(ignoredDescriptions, defaultValueDescription)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getPrettyOutput(left: string, right: string, rightAlignOfLeft: number, leftAlignOfRight: number, terminalWidth: number, colorLeft: boolean) {
|
||||
const res = [];
|
||||
let isFirstLine = true;
|
||||
let remainRight = right;
|
||||
const rightCharacterNumber = terminalWidth - leftAlignOfRight;
|
||||
while (remainRight.length > 0) {
|
||||
let curLeft = "";
|
||||
if (isFirstLine) {
|
||||
curLeft = padLeft(left, rightAlignOfLeft);
|
||||
curLeft = padRight(curLeft, leftAlignOfRight);
|
||||
curLeft = colorLeft ? colors.blue(curLeft) : curLeft;
|
||||
}
|
||||
else {
|
||||
curLeft = padLeft("", leftAlignOfRight);
|
||||
}
|
||||
|
||||
const curRight = remainRight.substr(0, rightCharacterNumber);
|
||||
remainRight = remainRight.slice(rightCharacterNumber);
|
||||
res.push(`${curLeft}${curRight}`);
|
||||
isFirstLine = false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function getValueCandidate(option: CommandLineOption): ValueCandidate | undefined {
|
||||
// option.type might be "string" | "number" | "boolean" | "object" | "list" | ESMap<string, number | string>
|
||||
// string -- any of: string
|
||||
// number -- any of: number
|
||||
// boolean -- any of: boolean
|
||||
// object -- null
|
||||
// list -- one or more: , content depends on `option.element.type`, the same as others
|
||||
// ESMap<string, number | string> -- any of: key1, key2, ....
|
||||
if (option.type === "object") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
valueType: getValueType(option),
|
||||
possibleValues: getPossibleValues(option)
|
||||
};
|
||||
|
||||
function getValueType(option: CommandLineOption) {
|
||||
switch (option.type) {
|
||||
case "string":
|
||||
case "number":
|
||||
case "boolean":
|
||||
return getDiagnosticText(Diagnostics.type_Colon);
|
||||
case "list":
|
||||
return getDiagnosticText(Diagnostics.one_or_more_Colon);
|
||||
default:
|
||||
return getDiagnosticText(Diagnostics.one_of_Colon);
|
||||
}
|
||||
}
|
||||
|
||||
function getPossibleValues(option: CommandLineOption) {
|
||||
let possibleValues: string;
|
||||
switch (option.type) {
|
||||
case "string":
|
||||
case "number":
|
||||
case "boolean":
|
||||
possibleValues = option.type;
|
||||
break;
|
||||
case "list":
|
||||
// TODO: check infinite loop
|
||||
possibleValues = getPossibleValues(option.element);
|
||||
break;
|
||||
case "object":
|
||||
possibleValues = "";
|
||||
break;
|
||||
default:
|
||||
// ESMap<string, number | string>
|
||||
const keys = arrayFrom(option.type.keys());
|
||||
possibleValues = keys.join(", ");
|
||||
}
|
||||
return possibleValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generateGroupOptionOutput(sys: System, optionsList: readonly CommandLineOption[]) {
|
||||
let maxLength = 0;
|
||||
for (const option of optionsList) {
|
||||
// If an option lacks a description,
|
||||
// it is not officially supported.
|
||||
if (!option.description) {
|
||||
const curLength = getDisplayNameTextOfOption(option).length;
|
||||
maxLength = maxLength > curLength ? maxLength : curLength;
|
||||
}
|
||||
|
||||
// left part should be right align, right part should be left align
|
||||
|
||||
// assume 2 space between left margin and left part.
|
||||
const rightAlignOfLeftPart = maxLength + 2;
|
||||
// assume 2 space between left and right part
|
||||
const leftAlignOfRightPart = rightAlignOfLeftPart + 2;
|
||||
let lines: string[] = [];
|
||||
for (const option of optionsList) {
|
||||
const tmp = generateOptionOutput(sys, option, rightAlignOfLeftPart, leftAlignOfRightPart);
|
||||
lines = [...lines, ...tmp];
|
||||
}
|
||||
// make sure always a blank line in the end.
|
||||
if (lines[lines.length - 2] !== sys.newLine) {
|
||||
lines.push(sys.newLine);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
function generateSectionOptionsOutput(sys: System, sectionName: string, options: readonly CommandLineOption[], subCategory: boolean, beforeOptionsDescription?: string, afterOptionsDescription?: string) {
|
||||
let res: string[] = [];
|
||||
res.push(createColors(sys).bold(sectionName) + sys.newLine + sys.newLine);
|
||||
if (beforeOptionsDescription) {
|
||||
res.push(beforeOptionsDescription + sys.newLine + sys.newLine);
|
||||
}
|
||||
if (!subCategory) {
|
||||
res = [...res, ...generateGroupOptionOutput(sys, options)];
|
||||
if (afterOptionsDescription) {
|
||||
res.push(afterOptionsDescription + sys.newLine + sys.newLine);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
const categoryMap = new Map<string, CommandLineOption[]>();
|
||||
for (const option of options) {
|
||||
if (!option.category) {
|
||||
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 = (option as CommandLineOptionOfListType).element;
|
||||
const typeMap = element.type as ESMap<string, number | string>;
|
||||
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);
|
||||
const curCategory = getDiagnosticText(option.category);
|
||||
const optionsOfCurCategory = categoryMap.get(curCategory) ?? [];
|
||||
optionsOfCurCategory.push(option);
|
||||
categoryMap.set(curCategory, optionsOfCurCategory);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
categoryMap.forEach((value, key) => {
|
||||
res.push(`### ${key}${sys.newLine}${sys.newLine}`);
|
||||
res = [...res, ...generateGroupOptionOutput(sys, value)];
|
||||
});
|
||||
if (afterOptionsDescription) {
|
||||
res.push(afterOptionsDescription + sys.newLine + sys.newLine);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function printEasyHelp(sys: System, simpleOptions: readonly CommandLineOption[]) {
|
||||
const colors = createColors(sys);
|
||||
let output: string[] = [...getHelpHeader(sys)];
|
||||
output.push(colors.bold(getDiagnosticText(Diagnostics.COMMON_COMMANDS)) + sys.newLine + sys.newLine);
|
||||
|
||||
example("tsc", Diagnostics.Compiles_the_current_project_tsconfig_json_in_the_working_directory);
|
||||
example("tsc app.ts util.ts", Diagnostics.Ignoring_tsconfig_json_compiles_the_specified_files_with_default_compiler_options);
|
||||
example("tsc -b", Diagnostics.Build_a_composite_project_in_the_working_directory);
|
||||
example("tsc --init", Diagnostics.Creates_a_tsconfig_json_with_the_recommended_settings_in_the_working_directory);
|
||||
example("tsc -p .path/to/tsconfig.json", Diagnostics.Compiles_the_TypeScript_project_located_at_the_specified_path);
|
||||
example("tsc --help --all", Diagnostics.An_expanded_version_of_this_information_showing_all_possible_compiler_options);
|
||||
example(["tsc --noEmit", "tsc --target esnext"], Diagnostics.Compiles_the_current_project_with_additional_settings);
|
||||
|
||||
const cliCommands = simpleOptions.filter(opt => opt.isCommandLineOnly || opt.category === Diagnostics.Command_line_Options);
|
||||
const configOpts = simpleOptions.filter(opt => !contains(cliCommands, opt));
|
||||
|
||||
output = [
|
||||
...output,
|
||||
...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.COMMAND_LINE_FLAGS), cliCommands, /*subCategory*/ false, /* beforeOptionsDescription */ undefined, /* afterOptionsDescription*/ undefined),
|
||||
...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.COMMON_COMPILER_OPTIONS), configOpts, /*subCategory*/ false, /* beforeOptionsDescription */ undefined, formatMessage(/*_dummy*/ undefined, Diagnostics.You_can_learn_about_all_of_the_compiler_options_at_0, "https://aka.ms/tsconfig-reference"))
|
||||
];
|
||||
|
||||
for (const line of output) {
|
||||
sys.write(line);
|
||||
}
|
||||
return;
|
||||
|
||||
function getParamType(option: CommandLineOption) {
|
||||
if (option.paramType !== undefined) {
|
||||
return " " + getDiagnosticText(option.paramType);
|
||||
function example(ex: string | string[], desc: DiagnosticMessage) {
|
||||
const examples = typeof ex === "string" ? [ex] : ex;
|
||||
for (const example of examples) {
|
||||
output.push(" " + colors.blue(example) + sys.newLine);
|
||||
}
|
||||
return "";
|
||||
output.push(" " + getDiagnosticText(desc) + sys.newLine + sys.newLine);
|
||||
}
|
||||
}
|
||||
|
||||
function makePadding(paddingLength: number): string {
|
||||
return Array(paddingLength + 1).join(" ");
|
||||
function printAllHelp(sys: System, compilerOptions: readonly CommandLineOption[], buildOptions: readonly CommandLineOption[], watchOptions: readonly CommandLineOption[]) {
|
||||
let output: string[] = [...getHelpHeader(sys)];
|
||||
output = [...output, ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.ALL_COMPILER_OPTIONS), compilerOptions, /*subCategory*/ true, /* beforeOptionsDescription */ undefined, formatMessage(/*_dummy*/ undefined, Diagnostics.You_can_learn_about_all_of_the_compiler_options_at_0, "https://aka.ms/tsconfig-reference"))];
|
||||
output = [...output, ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.WATCH_OPTIONS), watchOptions, /*subCategory*/ false, getDiagnosticText(Diagnostics.Including_watch_w_will_start_watching_the_current_project_for_the_file_changes_Once_set_you_can_config_watch_mode_with_Colon))];
|
||||
output = [...output, ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.BUILD_OPTIONS), buildOptions, /*subCategory*/ false, formatMessage(/*_dummy*/ undefined, Diagnostics.Using_build_b_will_make_tsc_behave_more_like_a_build_orchestrator_than_a_compiler_This_is_used_to_trigger_building_composite_projects_which_you_can_learn_more_about_at_0, "https://aka.ms/tsc-composite-builds"))];
|
||||
for (const line of output) {
|
||||
sys.write(line);
|
||||
}
|
||||
}
|
||||
|
||||
function printBuildHelp(sys: System, buildOptions: readonly CommandLineOption[]) {
|
||||
let output: string[] = [...getHelpHeader(sys)];
|
||||
output = [...output, ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.BUILD_OPTIONS), buildOptions, /*subCategory*/ false, formatMessage(/*_dummy*/ undefined, Diagnostics.Using_build_b_will_make_tsc_behave_more_like_a_build_orchestrator_than_a_compiler_This_is_used_to_trigger_building_composite_projects_which_you_can_learn_more_about_at_0, "https://aka.ms/tsc-composite-builds"))];
|
||||
for (const line of output) {
|
||||
sys.write(line);
|
||||
}
|
||||
}
|
||||
|
||||
function getHelpHeader(sys: System) {
|
||||
const colors = createColors(sys);
|
||||
const header: string[] = [];
|
||||
const tscExplanation = `${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${getDiagnosticText(Diagnostics.Version_0, version)}`;
|
||||
const terminalWidth = sys.getWidthOfTerminal?.() ?? 0;;
|
||||
const tsIconLength = 5;
|
||||
|
||||
const tsIconFirstLine = colors.blueBackground(padLeft("", tsIconLength));
|
||||
const tsIconSecondLine = colors.blueBackground(colors.white(padLeft("TS ", tsIconLength)));
|
||||
// If we have enough space, print TS icon.
|
||||
if (terminalWidth >= tscExplanation.length + tsIconLength) {
|
||||
// right align of the icon is 120 at most.
|
||||
const rightAlign = terminalWidth > 120 ? 120 : terminalWidth;
|
||||
const leftAlign = rightAlign - tsIconLength;
|
||||
header.push(padRight(tscExplanation, leftAlign) + tsIconFirstLine + sys.newLine);
|
||||
header.push(padLeft("", leftAlign) + tsIconSecondLine + sys.newLine);
|
||||
}
|
||||
else {
|
||||
header.push(tscExplanation + sys.newLine);
|
||||
header.push(sys.newLine);
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
function printHelp(sys: System, commandLine: ParsedCommandLine) {
|
||||
if (!commandLine.options.all) {
|
||||
printEasyHelp(sys, getOptionsForHelp(commandLine));
|
||||
}
|
||||
else {
|
||||
printAllHelp(sys, getOptionsForHelp(commandLine), optionsForBuild, optionsForWatch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,8 +452,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (commandLine.options.help || commandLine.options.all) {
|
||||
printVersion(sys);
|
||||
printHelp(sys, getOptionsForHelp(commandLine));
|
||||
printHelp(sys, commandLine);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
@@ -275,7 +494,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
printVersion(sys);
|
||||
printHelp(sys, getOptionsForHelp(commandLine));
|
||||
printHelp(sys, commandLine);
|
||||
}
|
||||
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
}
|
||||
@@ -463,13 +682,13 @@ namespace ts {
|
||||
|
||||
if (buildOptions.help) {
|
||||
printVersion(sys);
|
||||
printHelp(sys, buildOpts, "--build ");
|
||||
printBuildHelp(sys, buildOpts);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (projects.length === 0) {
|
||||
printVersion(sys);
|
||||
printHelp(sys, buildOpts, "--build ");
|
||||
printBuildHelp(sys, buildOpts);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
@@ -671,7 +890,7 @@ namespace ts {
|
||||
|
||||
if (canTrace(system, compilerOptions)) {
|
||||
startTracing(isBuildMode ? "build" : "project",
|
||||
compilerOptions.generateTrace!, compilerOptions.configFilePath);
|
||||
compilerOptions.generateTrace!, compilerOptions.configFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user