1import * as ts from "./_namespaces/ts"; 2import { 3 arrayFrom, BuilderProgram, BuildOptions, buildOpts, changeCompilerHostLikeToUseCache, CharacterCodes, combinePaths, 4 CommandLineOption, compareStringsCaseInsensitive, CompilerOptions, contains, convertToOptionsWithAbsolutePaths, 5 convertToTSConfig, createBuilderStatusReporter, createCompilerDiagnostic, createCompilerHostWorker, 6 createDiagnosticReporter, createGetCanonicalFileName, createIncrementalCompilerHost, createProgram, CreateProgram, 7 CreateProgramOptions, createSolutionBuilder, createSolutionBuilderHost, createSolutionBuilderWithWatch, 8 createSolutionBuilderWithWatchHost, createWatchCompilerHostOfConfigFile, 9 createWatchCompilerHostOfFilesAndCompilerOptions, createWatchProgram, Debug, Diagnostic, DiagnosticMessage, 10 DiagnosticReporter, Diagnostics, dumpTracingLegend, EmitAndSemanticDiagnosticsBuilderProgram, 11 emitFilesAndReportErrorsAndGetExitStatus, ESMap, ExitStatus, ExtendedConfigCacheEntry, Extension, fileExtensionIs, 12 fileExtensionIsOneOf, filter, findConfigFile, forEach, formatMessage, generateTSConfig, 13 getBuildOrderFromAnyBuildOrder, getCompilerOptionsDiffValue, getConfigFileParsingDiagnostics, getDiagnosticText, 14 getEntries, getErrorSummaryText, getLineStarts, getNormalizedAbsolutePath, isIncrementalCompilation, isWatchSet, 15 Map, normalizePath, optionDeclarations, optionsForBuild, optionsForWatch, padLeft, padRight, parseBuildCommand, 16 parseCommandLine, parseConfigFileWithSystem, ParsedCommandLine, Program, reduceLeftIterator, ReportEmitErrorSummary, 17 SolutionBuilder, SolutionBuilderHostBase, sort, SourceFile, startsWith, startTracing, stringContains, 18 supportedJSExtensionsFlat, supportedTSExtensionsFlat, sys, System, toPath, tracing, validateLocaleAndSetLanguage, 19 version, WatchCompilerHost, WatchOptions, 20} from "./_namespaces/ts"; 21import * as performance from "../compiler/_namespaces/ts.performance"; 22 23interface Statistic { 24 name: string; 25 value: number; 26 type: StatisticType; 27} 28 29export enum StatisticType { 30 time, 31 count, 32 memory, 33} 34 35function countLines(program: Program): Map<number> { 36 const counts = getCountsMap(); 37 forEach(program.getSourceFiles(), file => { 38 const key = getCountKey(program, file); 39 const lineCount = getLineStarts(file).length; 40 counts.set(key, counts.get(key)! + lineCount); 41 }); 42 return counts; 43} 44 45function getCountsMap() { 46 const counts = new Map<string, number>(); 47 counts.set("Library", 0); 48 counts.set("Definitions", 0); 49 counts.set("TypeScript", 0); 50 counts.set("JavaScript", 0); 51 counts.set("JSON", 0); 52 counts.set("Other", 0); 53 return counts; 54} 55 56function getCountKey(program: Program, file: SourceFile) { 57 if (program.isSourceFileDefaultLibrary(file)) { 58 return "Library"; 59 } 60 else if (file.isDeclarationFile) { 61 return "Definitions"; 62 } 63 64 const path = file.path; 65 if (fileExtensionIsOneOf(path, supportedTSExtensionsFlat)) { 66 return "TypeScript"; 67 } 68 else if (fileExtensionIsOneOf(path, supportedJSExtensionsFlat)) { 69 return "JavaScript"; 70 } 71 else if (fileExtensionIs(path, Extension.Json)) { 72 return "JSON"; 73 } 74 else { 75 return "Other"; 76 } 77} 78 79function updateReportDiagnostic( 80 sys: System, 81 existing: DiagnosticReporter, 82 options: CompilerOptions | BuildOptions 83): DiagnosticReporter { 84 return shouldBePretty(sys, options) ? 85 createDiagnosticReporter(sys, /*pretty*/ true) : 86 existing; 87} 88 89function defaultIsPretty(sys: System) { 90 return !!sys.writeOutputIsTTY && sys.writeOutputIsTTY() && !sys.getEnvironmentVariable("NO_COLOR"); 91} 92 93function shouldBePretty(sys: System, options: CompilerOptions | BuildOptions) { 94 if (!options || typeof options.pretty === "undefined") { 95 return defaultIsPretty(sys); 96 } 97 return options.pretty; 98} 99 100function getOptionsForHelp(commandLine: ParsedCommandLine) { 101 // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") 102 return !!commandLine.options.all ? 103 sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) : 104 filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView); 105} 106 107function printVersion(sys: System) { 108 sys.write(getDiagnosticText(Diagnostics.Version_0, version) + sys.newLine); 109} 110 111function createColors(sys: System) { 112 const showColors = defaultIsPretty(sys); 113 if (!showColors) { 114 return { 115 bold: (str: string) => str, 116 blue: (str: string) => str, 117 blueBackground: (str: string) => str, 118 brightWhite: (str: string) => str 119 }; 120 } 121 122 function bold(str: string) { 123 return `\x1b[1m${str}\x1b[22m`; 124 } 125 126 const isWindows = sys.getEnvironmentVariable("OS") && stringContains(sys.getEnvironmentVariable("OS").toLowerCase(), "windows"); 127 const isWindowsTerminal = sys.getEnvironmentVariable("WT_SESSION"); 128 const isVSCode = sys.getEnvironmentVariable("TERM_PROGRAM") && sys.getEnvironmentVariable("TERM_PROGRAM") === "vscode"; 129 130 function blue(str: string) { 131 // Effectively Powershell and Command prompt users use cyan instead 132 // of blue because the default theme doesn't show blue with enough contrast. 133 if (isWindows && !isWindowsTerminal && !isVSCode) { 134 return brightWhite(str); 135 } 136 137 return `\x1b[94m${str}\x1b[39m`; 138 } 139 140 // There are ~3 types of terminal color support: 16 colors, 256 and 16m colors 141 // If there is richer color support, e.g. 256+ we can use extended ANSI codes which are not just generic 'blue' 142 // but a 'lighter blue' which is closer to the blue in the TS logo. 143 const supportsRicherColors = sys.getEnvironmentVariable("COLORTERM") === "truecolor" || sys.getEnvironmentVariable("TERM") === "xterm-256color"; 144 function blueBackground(str: string) { 145 if (supportsRicherColors) { 146 return `\x1B[48;5;68m${str}\x1B[39;49m`; 147 } 148 else { 149 return `\x1b[44m${str}\x1B[39;49m`; 150 } 151 } 152 function brightWhite(str: string) { 153 return `\x1b[97m${str}\x1b[39m`; 154 } 155 return { 156 bold, 157 blue, 158 brightWhite, 159 blueBackground 160 }; 161} 162 163function getDisplayNameTextOfOption(option: CommandLineOption) { 164 return `--${option.name}${option.shortName ? `, -${option.shortName}` : ""}`; 165} 166 167function generateOptionOutput(sys: System, option: CommandLineOption, rightAlignOfLeft: number, leftAlignOfRight: number) { 168 interface ValueCandidate { 169 // "one or more" or "any of" 170 valueType: string; 171 possibleValues: string; 172 } 173 174 const text: string[] = []; 175 const colors = createColors(sys); 176 177 // name and description 178 const name = getDisplayNameTextOfOption(option); 179 180 // value type and possible value 181 const valueCandidates = getValueCandidate(option); 182 const defaultValueDescription = 183 typeof option.defaultValueDescription === "object" 184 ? getDiagnosticText(option.defaultValueDescription) 185 : formatDefaultValue( 186 option.defaultValueDescription, 187 option.type === "list" ? option.element.type : option.type 188 ); 189 const terminalWidth = sys.getWidthOfTerminal?.() ?? 0; 190 191 // Note: child_process might return `terminalWidth` as undefined. 192 if (terminalWidth >= 80) { 193 let description = ""; 194 if (option.description) { 195 description = getDiagnosticText(option.description); 196 } 197 text.push(...getPrettyOutput(name, description, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ true), sys.newLine); 198 if (showAdditionalInfoOutput(valueCandidates, option)) { 199 if (valueCandidates) { 200 text.push(...getPrettyOutput(valueCandidates.valueType, valueCandidates.possibleValues, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ false), sys.newLine); 201 } 202 if (defaultValueDescription) { 203 text.push(...getPrettyOutput(getDiagnosticText(Diagnostics.default_Colon), defaultValueDescription, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ false), sys.newLine); 204 } 205 } 206 text.push(sys.newLine); 207 } 208 else { 209 text.push(colors.blue(name), sys.newLine); 210 if (option.description) { 211 const description = getDiagnosticText(option.description); 212 text.push(description); 213 } 214 text.push(sys.newLine); 215 if (showAdditionalInfoOutput(valueCandidates, option)) { 216 if (valueCandidates) { 217 text.push(`${valueCandidates.valueType} ${valueCandidates.possibleValues}`); 218 } 219 if (defaultValueDescription) { 220 if (valueCandidates) text.push(sys.newLine); 221 const diagType = getDiagnosticText(Diagnostics.default_Colon); 222 text.push(`${diagType} ${defaultValueDescription}`); 223 } 224 225 text.push(sys.newLine); 226 } 227 text.push(sys.newLine); 228 } 229 return text; 230 231 function formatDefaultValue( 232 defaultValue: CommandLineOption["defaultValueDescription"], 233 type: CommandLineOption["type"] 234 ) { 235 return defaultValue !== undefined && typeof type === "object" 236 // e.g. ScriptTarget.ES2015 -> "es6/es2015" 237 ? arrayFrom(type.entries()) 238 .filter(([, value]) => value === defaultValue) 239 .map(([name]) => name) 240 .join("/") 241 : String(defaultValue); 242 } 243 244 function showAdditionalInfoOutput(valueCandidates: ValueCandidate | undefined, option: CommandLineOption): boolean { 245 const ignoreValues = ["string"]; 246 const ignoredDescriptions = [undefined, "false", "n/a"]; 247 const defaultValueDescription = option.defaultValueDescription; 248 if (option.category === Diagnostics.Command_line_Options) return false; 249 250 if (contains(ignoreValues, valueCandidates?.possibleValues) && contains(ignoredDescriptions, defaultValueDescription)) { 251 return false; 252 } 253 return true; 254 } 255 256 function getPrettyOutput(left: string, right: string, rightAlignOfLeft: number, leftAlignOfRight: number, terminalWidth: number, colorLeft: boolean) { 257 const res = []; 258 let isFirstLine = true; 259 let remainRight = right; 260 const rightCharacterNumber = terminalWidth - leftAlignOfRight; 261 while (remainRight.length > 0) { 262 let curLeft = ""; 263 if (isFirstLine) { 264 curLeft = padLeft(left, rightAlignOfLeft); 265 curLeft = padRight(curLeft, leftAlignOfRight); 266 curLeft = colorLeft ? colors.blue(curLeft) : curLeft; 267 } 268 else { 269 curLeft = padLeft("", leftAlignOfRight); 270 } 271 272 const curRight = remainRight.substr(0, rightCharacterNumber); 273 remainRight = remainRight.slice(rightCharacterNumber); 274 res.push(`${curLeft}${curRight}`); 275 isFirstLine = false; 276 } 277 return res; 278 } 279 280 function getValueCandidate(option: CommandLineOption): ValueCandidate | undefined { 281 // option.type might be "string" | "number" | "boolean" | "object" | "list" | ESMap<string, number | string> 282 // string -- any of: string 283 // number -- any of: number 284 // boolean -- any of: boolean 285 // object -- null 286 // list -- one or more: , content depends on `option.element.type`, the same as others 287 // ESMap<string, number | string> -- any of: key1, key2, .... 288 if (option.type === "object") { 289 return undefined; 290 } 291 292 return { 293 valueType: getValueType(option), 294 possibleValues: getPossibleValues(option) 295 }; 296 297 function getValueType(option: CommandLineOption) { 298 switch (option.type) { 299 case "string": 300 case "number": 301 case "boolean": 302 return getDiagnosticText(Diagnostics.type_Colon); 303 case "list": 304 return getDiagnosticText(Diagnostics.one_or_more_Colon); 305 default: 306 return getDiagnosticText(Diagnostics.one_of_Colon); 307 } 308 } 309 310 function getPossibleValues(option: CommandLineOption) { 311 let possibleValues: string; 312 switch (option.type) { 313 case "string": 314 case "number": 315 case "boolean": 316 possibleValues = option.type; 317 break; 318 case "list": 319 // TODO: check infinite loop 320 possibleValues = getPossibleValues(option.element); 321 break; 322 case "object": 323 possibleValues = ""; 324 break; 325 default: 326 // ESMap<string, number | string> 327 // Group synonyms: es6/es2015 328 const inverted: { [value: string]: string[] } = {}; 329 option.type.forEach((value, name) => { 330 (inverted[value] ||= []).push(name); 331 }); 332 return getEntries(inverted) 333 .map(([, synonyms]) => synonyms.join("/")) 334 .join(", "); 335 } 336 return possibleValues; 337 } 338 } 339} 340 341function generateGroupOptionOutput(sys: System, optionsList: readonly CommandLineOption[]) { 342 let maxLength = 0; 343 for (const option of optionsList) { 344 const curLength = getDisplayNameTextOfOption(option).length; 345 maxLength = maxLength > curLength ? maxLength : curLength; 346 } 347 348 // left part should be right align, right part should be left align 349 350 // assume 2 space between left margin and left part. 351 const rightAlignOfLeftPart = maxLength + 2; 352 // assume 2 space between left and right part 353 const leftAlignOfRightPart = rightAlignOfLeftPart + 2; 354 let lines: string[] = []; 355 for (const option of optionsList) { 356 const tmp = generateOptionOutput(sys, option, rightAlignOfLeftPart, leftAlignOfRightPart); 357 lines = [...lines, ...tmp]; 358 } 359 // make sure always a blank line in the end. 360 if (lines[lines.length - 2] !== sys.newLine) { 361 lines.push(sys.newLine); 362 } 363 return lines; 364} 365 366function generateSectionOptionsOutput(sys: System, sectionName: string, options: readonly CommandLineOption[], subCategory: boolean, beforeOptionsDescription?: string, afterOptionsDescription?: string) { 367 let res: string[] = []; 368 res.push(createColors(sys).bold(sectionName) + sys.newLine + sys.newLine); 369 if (beforeOptionsDescription) { 370 res.push(beforeOptionsDescription + sys.newLine + sys.newLine); 371 } 372 if (!subCategory) { 373 res = [...res, ...generateGroupOptionOutput(sys, options)]; 374 if (afterOptionsDescription) { 375 res.push(afterOptionsDescription + sys.newLine + sys.newLine); 376 } 377 return res; 378 } 379 const categoryMap = new Map<string, CommandLineOption[]>(); 380 for (const option of options) { 381 if (!option.category) { 382 continue; 383 } 384 const curCategory = getDiagnosticText(option.category); 385 const optionsOfCurCategory = categoryMap.get(curCategory) ?? []; 386 optionsOfCurCategory.push(option); 387 categoryMap.set(curCategory, optionsOfCurCategory); 388 } 389 categoryMap.forEach((value, key) => { 390 res.push(`### ${key}${sys.newLine}${sys.newLine}`); 391 res = [...res, ...generateGroupOptionOutput(sys, value)]; 392 }); 393 if (afterOptionsDescription) { 394 res.push(afterOptionsDescription + sys.newLine + sys.newLine); 395 } 396 return res; 397} 398 399function printEasyHelp(sys: System, simpleOptions: readonly CommandLineOption[]) { 400 const colors = createColors(sys); 401 let output: string[] = [...getHeader(sys,`${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${getDiagnosticText(Diagnostics.Version_0, version)}`)]; 402 output.push(colors.bold(getDiagnosticText(Diagnostics.COMMON_COMMANDS)) + sys.newLine + sys.newLine); 403 404 example("tsc", Diagnostics.Compiles_the_current_project_tsconfig_json_in_the_working_directory); 405 example("tsc app.ts util.ts", Diagnostics.Ignoring_tsconfig_json_compiles_the_specified_files_with_default_compiler_options); 406 example("tsc -b", Diagnostics.Build_a_composite_project_in_the_working_directory); 407 example("tsc --init", Diagnostics.Creates_a_tsconfig_json_with_the_recommended_settings_in_the_working_directory); 408 example("tsc -p ./path/to/tsconfig.json", Diagnostics.Compiles_the_TypeScript_project_located_at_the_specified_path); 409 example("tsc --help --all", Diagnostics.An_expanded_version_of_this_information_showing_all_possible_compiler_options); 410 example(["tsc --noEmit", "tsc --target esnext"], Diagnostics.Compiles_the_current_project_with_additional_settings); 411 412 const cliCommands = simpleOptions.filter(opt => opt.isCommandLineOnly || opt.category === Diagnostics.Command_line_Options); 413 const configOpts = simpleOptions.filter(opt => !contains(cliCommands, opt)); 414 415 output = [ 416 ...output, 417 ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.COMMAND_LINE_FLAGS), cliCommands, /*subCategory*/ false, /* beforeOptionsDescription */ undefined, /* afterOptionsDescription*/ undefined), 418 ...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/tsc")) 419 ]; 420 421 for (const line of output) { 422 sys.write(line); 423 } 424 425 function example(ex: string | string[], desc: DiagnosticMessage) { 426 const examples = typeof ex === "string" ? [ex] : ex; 427 for (const example of examples) { 428 output.push(" " + colors.blue(example) + sys.newLine); 429 } 430 output.push(" " + getDiagnosticText(desc) + sys.newLine + sys.newLine); 431 } 432} 433 434function printAllHelp(sys: System, compilerOptions: readonly CommandLineOption[], buildOptions: readonly CommandLineOption[], watchOptions: readonly CommandLineOption[]) { 435 let output: string[] = [...getHeader(sys,`${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${getDiagnosticText(Diagnostics.Version_0, version)}`)]; 436 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/tsc"))]; 437 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))]; 438 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"))]; 439 for (const line of output) { 440 sys.write(line); 441 } 442} 443 444function printBuildHelp(sys: System, buildOptions: readonly CommandLineOption[]) { 445 let output: string[] = [...getHeader(sys,`${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${getDiagnosticText(Diagnostics.Version_0, version)}`)]; 446 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"))]; 447 for (const line of output) { 448 sys.write(line); 449 } 450} 451 452function getHeader(sys: System, message: string) { 453 const colors = createColors(sys); 454 const header: string[] = []; 455 const terminalWidth = sys.getWidthOfTerminal?.() ?? 0; 456 const tsIconLength = 5; 457 458 const tsIconFirstLine = colors.blueBackground(padLeft("", tsIconLength)); 459 const tsIconSecondLine = colors.blueBackground(colors.brightWhite(padLeft("TS ", tsIconLength))); 460 // If we have enough space, print TS icon. 461 if (terminalWidth >= message.length + tsIconLength) { 462 // right align of the icon is 120 at most. 463 const rightAlign = terminalWidth > 120 ? 120 : terminalWidth; 464 const leftAlign = rightAlign - tsIconLength; 465 header.push(padRight(message, leftAlign) + tsIconFirstLine + sys.newLine); 466 header.push(padLeft("", leftAlign) + tsIconSecondLine + sys.newLine); 467 } 468 else { 469 header.push(message + sys.newLine); 470 header.push(sys.newLine); 471 } 472 return header; 473} 474 475function printHelp(sys: System, commandLine: ParsedCommandLine) { 476 if (!commandLine.options.all) { 477 printEasyHelp(sys, getOptionsForHelp(commandLine)); 478 } 479 else { 480 printAllHelp(sys, getOptionsForHelp(commandLine), optionsForBuild, optionsForWatch); 481 } 482} 483 484function executeCommandLineWorker( 485 sys: System, 486 cb: ExecuteCommandLineCallbacks, 487 commandLine: ParsedCommandLine, 488) { 489 let reportDiagnostic = createDiagnosticReporter(sys); 490 if (commandLine.options.build) { 491 reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_build_must_be_the_first_command_line_argument)); 492 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 493 } 494 495 // Configuration file name (if any) 496 let configFileName: string | undefined; 497 if (commandLine.options.locale) { 498 validateLocaleAndSetLanguage(commandLine.options.locale, sys, commandLine.errors); 499 } 500 501 // If there are any errors due to command line parsing and/or 502 // setting up localization, report them and quit. 503 if (commandLine.errors.length > 0) { 504 commandLine.errors.forEach(reportDiagnostic); 505 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 506 } 507 508 if (commandLine.options.init) { 509 writeConfigFile(sys, reportDiagnostic, commandLine.options, commandLine.fileNames); 510 return sys.exit(ExitStatus.Success); 511 } 512 513 if (commandLine.options.version) { 514 printVersion(sys); 515 return sys.exit(ExitStatus.Success); 516 } 517 518 if (commandLine.options.help || commandLine.options.all) { 519 printHelp(sys, commandLine); 520 return sys.exit(ExitStatus.Success); 521 } 522 523 if (commandLine.options.watch && commandLine.options.listFilesOnly) { 524 reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "listFilesOnly")); 525 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 526 } 527 528 if (commandLine.options.project) { 529 if (commandLine.fileNames.length !== 0) { 530 reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line)); 531 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 532 } 533 534 const fileOrDirectory = normalizePath(commandLine.options.project); 535 if (!fileOrDirectory /* current directory "." */ || sys.directoryExists(fileOrDirectory)) { 536 configFileName = combinePaths(fileOrDirectory, "tsconfig.json"); 537 if (!sys.fileExists(configFileName)) { 538 reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project)); 539 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 540 } 541 } 542 else { 543 configFileName = fileOrDirectory; 544 if (!sys.fileExists(configFileName)) { 545 reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project)); 546 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 547 } 548 } 549 } 550 else if (commandLine.fileNames.length === 0) { 551 const searchPath = normalizePath(sys.getCurrentDirectory()); 552 configFileName = findConfigFile(searchPath, fileName => sys.fileExists(fileName)); 553 } 554 555 if (commandLine.fileNames.length === 0 && !configFileName) { 556 if (commandLine.options.showConfig) { 557 reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_current_directory_Colon_0, normalizePath(sys.getCurrentDirectory()))); 558 } 559 else { 560 printVersion(sys); 561 printHelp(sys, commandLine); 562 } 563 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 564 } 565 566 const currentDirectory = sys.getCurrentDirectory(); 567 const commandLineOptions = convertToOptionsWithAbsolutePaths( 568 commandLine.options, 569 fileName => getNormalizedAbsolutePath(fileName, currentDirectory) 570 ); 571 if (configFileName) { 572 const extendedConfigCache = new Map<string, ExtendedConfigCacheEntry>(); 573 const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, extendedConfigCache, commandLine.watchOptions, sys, reportDiagnostic)!; // TODO: GH#18217 574 if (commandLineOptions.showConfig) { 575 if (configParseResult.errors.length !== 0) { 576 reportDiagnostic = updateReportDiagnostic( 577 sys, 578 reportDiagnostic, 579 configParseResult.options 580 ); 581 configParseResult.errors.forEach(reportDiagnostic); 582 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 583 } 584 // eslint-disable-next-line no-null/no-null 585 sys.write(JSON.stringify(convertToTSConfig(configParseResult, configFileName, sys), null, 4) + sys.newLine); 586 return sys.exit(ExitStatus.Success); 587 } 588 reportDiagnostic = updateReportDiagnostic( 589 sys, 590 reportDiagnostic, 591 configParseResult.options 592 ); 593 if (isWatchSet(configParseResult.options)) { 594 if (reportWatchModeWithoutSysSupport(sys, reportDiagnostic)) return; 595 return createWatchOfConfigFile( 596 sys, 597 cb, 598 reportDiagnostic, 599 configParseResult, 600 commandLineOptions, 601 commandLine.watchOptions, 602 extendedConfigCache, 603 ); 604 } 605 else if (isIncrementalCompilation(configParseResult.options)) { 606 performIncrementalCompilation( 607 sys, 608 cb, 609 reportDiagnostic, 610 configParseResult 611 ); 612 } 613 else { 614 performCompilation( 615 sys, 616 cb, 617 reportDiagnostic, 618 configParseResult 619 ); 620 } 621 } 622 else { 623 if (commandLineOptions.showConfig) { 624 // eslint-disable-next-line no-null/no-null 625 sys.write(JSON.stringify(convertToTSConfig(commandLine, combinePaths(currentDirectory, "tsconfig.json"), sys), null, 4) + sys.newLine); 626 return sys.exit(ExitStatus.Success); 627 } 628 reportDiagnostic = updateReportDiagnostic( 629 sys, 630 reportDiagnostic, 631 commandLineOptions 632 ); 633 if (isWatchSet(commandLineOptions)) { 634 if (reportWatchModeWithoutSysSupport(sys, reportDiagnostic)) return; 635 return createWatchOfFilesAndCompilerOptions( 636 sys, 637 cb, 638 reportDiagnostic, 639 commandLine.fileNames, 640 commandLineOptions, 641 commandLine.watchOptions, 642 ); 643 } 644 else if (isIncrementalCompilation(commandLineOptions)) { 645 performIncrementalCompilation( 646 sys, 647 cb, 648 reportDiagnostic, 649 { ...commandLine, options: commandLineOptions } 650 ); 651 } 652 else { 653 performCompilation( 654 sys, 655 cb, 656 reportDiagnostic, 657 { ...commandLine, options: commandLineOptions } 658 ); 659 } 660 } 661} 662 663export function isBuild(commandLineArgs: readonly string[]) { 664 if (commandLineArgs.length > 0 && commandLineArgs[0].charCodeAt(0) === CharacterCodes.minus) { 665 const firstOption = commandLineArgs[0].slice(commandLineArgs[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase(); 666 return firstOption === "build" || firstOption === "b"; 667 } 668 return false; 669} 670 671export type ExecuteCommandLineCallbacks = (program: Program | BuilderProgram | ParsedCommandLine) => void; 672export function executeCommandLine( 673 system: System, 674 cb: ExecuteCommandLineCallbacks, 675 commandLineArgs: readonly string[], 676) { 677 if (isBuild(commandLineArgs)) { 678 const { buildOptions, watchOptions, projects, errors } = parseBuildCommand(commandLineArgs.slice(1)); 679 if (buildOptions.generateCpuProfile && system.enableCPUProfiler) { 680 system.enableCPUProfiler(buildOptions.generateCpuProfile, () => performBuild( 681 system, 682 cb, 683 buildOptions, 684 watchOptions, 685 projects, 686 errors 687 )); 688 } 689 else { 690 return performBuild( 691 system, 692 cb, 693 buildOptions, 694 watchOptions, 695 projects, 696 errors 697 ); 698 } 699 } 700 701 const commandLine = parseCommandLine(commandLineArgs, path => system.readFile(path)); 702 if (commandLine.options.generateCpuProfile && system.enableCPUProfiler) { 703 system.enableCPUProfiler(commandLine.options.generateCpuProfile, () => executeCommandLineWorker( 704 system, 705 cb, 706 commandLine, 707 )); 708 } 709 else { 710 return executeCommandLineWorker(system, cb, commandLine); 711 } 712} 713 714function reportWatchModeWithoutSysSupport(sys: System, reportDiagnostic: DiagnosticReporter) { 715 if (!sys.watchFile || !sys.watchDirectory) { 716 reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch")); 717 sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 718 return true; 719 } 720 return false; 721} 722 723function performBuild( 724 sys: System, 725 cb: ExecuteCommandLineCallbacks, 726 buildOptions: BuildOptions, 727 watchOptions: WatchOptions | undefined, 728 projects: string[], 729 errors: Diagnostic[] 730) { 731 // Update to pretty if host supports it 732 const reportDiagnostic = updateReportDiagnostic( 733 sys, 734 createDiagnosticReporter(sys), 735 buildOptions 736 ); 737 738 if (buildOptions.locale) { 739 validateLocaleAndSetLanguage(buildOptions.locale, sys, errors); 740 } 741 742 if (errors.length > 0) { 743 errors.forEach(reportDiagnostic); 744 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 745 } 746 747 if (buildOptions.help) { 748 printVersion(sys); 749 printBuildHelp(sys, buildOpts); 750 return sys.exit(ExitStatus.Success); 751 } 752 753 if (projects.length === 0) { 754 printVersion(sys); 755 printBuildHelp(sys, buildOpts); 756 return sys.exit(ExitStatus.Success); 757 } 758 759 if (!sys.getModifiedTime || !sys.setModifiedTime || (buildOptions.clean && !sys.deleteFile)) { 760 reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build")); 761 return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); 762 } 763 764 if (buildOptions.watch) { 765 if (reportWatchModeWithoutSysSupport(sys, reportDiagnostic)) return; 766 const buildHost = createSolutionBuilderWithWatchHost( 767 sys, 768 /*createProgram*/ undefined, 769 reportDiagnostic, 770 createBuilderStatusReporter(sys, shouldBePretty(sys, buildOptions)), 771 createWatchStatusReporter(sys, buildOptions) 772 ); 773 const solutionPerformance = enableSolutionPerformance(sys, buildOptions); 774 updateSolutionBuilderHost(sys, cb, buildHost, solutionPerformance); 775 const onWatchStatusChange = buildHost.onWatchStatusChange; 776 buildHost.onWatchStatusChange = (d, newLine, options, errorCount) => { 777 onWatchStatusChange?.(d, newLine, options, errorCount); 778 if (d.code === Diagnostics.Found_0_errors_Watching_for_file_changes.code || 779 d.code === Diagnostics.Found_1_error_Watching_for_file_changes.code) { 780 reportSolutionBuilderTimes(builder, solutionPerformance); 781 } 782 }; 783 const builder = createSolutionBuilderWithWatch(buildHost, projects, buildOptions, watchOptions); 784 builder.build(); 785 return builder; 786 } 787 788 const buildHost = createSolutionBuilderHost( 789 sys, 790 /*createProgram*/ undefined, 791 reportDiagnostic, 792 createBuilderStatusReporter(sys, shouldBePretty(sys, buildOptions)), 793 createReportErrorSummary(sys, buildOptions) 794 ); 795 const solutionPerformance = enableSolutionPerformance(sys, buildOptions); 796 updateSolutionBuilderHost(sys, cb, buildHost, solutionPerformance); 797 const builder = createSolutionBuilder(buildHost, projects, buildOptions); 798 const exitStatus = buildOptions.clean ? builder.clean() : builder.build(); 799 reportSolutionBuilderTimes(builder, solutionPerformance); 800 dumpTracingLegend(); // Will no-op if there hasn't been any tracing 801 return sys.exit(exitStatus); 802} 803 804function createReportErrorSummary(sys: System, options: CompilerOptions | BuildOptions): ReportEmitErrorSummary | undefined { 805 return shouldBePretty(sys, options) ? 806 (errorCount, filesInError) => sys.write(getErrorSummaryText(errorCount, filesInError, sys.newLine, sys)) : 807 undefined; 808} 809 810function performCompilation( 811 sys: System, 812 cb: ExecuteCommandLineCallbacks, 813 reportDiagnostic: DiagnosticReporter, 814 config: ParsedCommandLine 815) { 816 const { fileNames, options, projectReferences } = config; 817 const host = createCompilerHostWorker(options, /*setParentPos*/ undefined, sys); 818 const currentDirectory = host.getCurrentDirectory(); 819 const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); 820 changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName)); 821 enableStatisticsAndTracing(sys, options, /*isBuildMode*/ false); 822 823 const programOptions: CreateProgramOptions = { 824 rootNames: fileNames, 825 options, 826 projectReferences, 827 host, 828 configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config) 829 }; 830 const program = createProgram(programOptions); 831 const exitStatus = emitFilesAndReportErrorsAndGetExitStatus( 832 program, 833 reportDiagnostic, 834 s => sys.write(s + sys.newLine), 835 createReportErrorSummary(sys, options) 836 ); 837 reportStatistics(sys, program, /*builder*/ undefined); 838 cb(program); 839 return sys.exit(exitStatus); 840} 841 842function performIncrementalCompilation( 843 sys: System, 844 cb: ExecuteCommandLineCallbacks, 845 reportDiagnostic: DiagnosticReporter, 846 config: ParsedCommandLine 847) { 848 const { options, fileNames, projectReferences } = config; 849 enableStatisticsAndTracing(sys, options, /*isBuildMode*/ false); 850 const host = createIncrementalCompilerHost(options, sys); 851 const exitStatus = ts.performIncrementalCompilation({ 852 host, 853 system: sys, 854 rootNames: fileNames, 855 options, 856 configFileParsingDiagnostics: getConfigFileParsingDiagnostics(config), 857 projectReferences, 858 reportDiagnostic, 859 reportErrorSummary: createReportErrorSummary(sys, options), 860 afterProgramEmitAndDiagnostics: builderProgram => { 861 reportStatistics(sys, builderProgram.getProgram(), /*builder*/ undefined); 862 cb(builderProgram); 863 } 864 }); 865 return sys.exit(exitStatus); 866} 867 868function updateSolutionBuilderHost( 869 sys: System, 870 cb: ExecuteCommandLineCallbacks, 871 buildHost: SolutionBuilderHostBase<EmitAndSemanticDiagnosticsBuilderProgram>, 872 solutionPerformance: SolutionPerformance | undefined, 873) { 874 updateCreateProgram(sys, buildHost, /*isBuildMode*/ true); 875 buildHost.afterProgramEmitAndDiagnostics = program => { 876 reportStatistics(sys, program.getProgram(), solutionPerformance); 877 cb(program); 878 }; 879 buildHost.afterEmitBundle = cb; 880} 881 882function updateCreateProgram<T extends BuilderProgram>(sys: System, host: { createProgram: CreateProgram<T>; }, isBuildMode: boolean) { 883 const compileUsingBuilder = host.createProgram; 884 host.createProgram = (rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences) => { 885 Debug.assert(rootNames !== undefined || (options === undefined && !!oldProgram)); 886 if (options !== undefined) { 887 enableStatisticsAndTracing(sys, options, isBuildMode); 888 } 889 return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences); 890 }; 891} 892 893function updateWatchCompilationHost( 894 sys: System, 895 cb: ExecuteCommandLineCallbacks, 896 watchCompilerHost: WatchCompilerHost<EmitAndSemanticDiagnosticsBuilderProgram>, 897) { 898 updateCreateProgram(sys, watchCompilerHost, /*isBuildMode*/ false); 899 const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217 900 watchCompilerHost.afterProgramCreate = builderProgram => { 901 emitFilesUsingBuilder(builderProgram); 902 reportStatistics(sys, builderProgram.getProgram(), /*builder*/ undefined); 903 cb(builderProgram); 904 }; 905} 906 907function createWatchStatusReporter(sys: System, options: CompilerOptions | BuildOptions) { 908 return ts.createWatchStatusReporter(sys, shouldBePretty(sys, options)); 909} 910 911function createWatchOfConfigFile( 912 system: System, 913 cb: ExecuteCommandLineCallbacks, 914 reportDiagnostic: DiagnosticReporter, 915 configParseResult: ParsedCommandLine, 916 optionsToExtend: CompilerOptions, 917 watchOptionsToExtend: WatchOptions | undefined, 918 extendedConfigCache: Map<ExtendedConfigCacheEntry>, 919) { 920 const watchCompilerHost = createWatchCompilerHostOfConfigFile({ 921 configFileName: configParseResult.options.configFilePath!, 922 optionsToExtend, 923 watchOptionsToExtend, 924 system, 925 reportDiagnostic, 926 reportWatchStatus: createWatchStatusReporter(system, configParseResult.options) 927 }); 928 updateWatchCompilationHost(system, cb, watchCompilerHost); 929 watchCompilerHost.configFileParsingResult = configParseResult; 930 watchCompilerHost.extendedConfigCache = extendedConfigCache; 931 return createWatchProgram(watchCompilerHost); 932} 933 934function createWatchOfFilesAndCompilerOptions( 935 system: System, 936 cb: ExecuteCommandLineCallbacks, 937 reportDiagnostic: DiagnosticReporter, 938 rootFiles: string[], 939 options: CompilerOptions, 940 watchOptions: WatchOptions | undefined, 941) { 942 const watchCompilerHost = createWatchCompilerHostOfFilesAndCompilerOptions({ 943 rootFiles, 944 options, 945 watchOptions, 946 system, 947 reportDiagnostic, 948 reportWatchStatus: createWatchStatusReporter(system, options) 949 }); 950 updateWatchCompilationHost(system, cb, watchCompilerHost); 951 return createWatchProgram(watchCompilerHost); 952} 953 954interface SolutionPerformance { 955 addAggregateStatistic(s: Statistic): void; 956 forEachAggregateStatistics(cb: (s: Statistic) => void): void; 957 clear(): void; 958} 959 960function enableSolutionPerformance(system: System, options: BuildOptions) { 961 if (system === sys && options.extendedDiagnostics) { 962 performance.enable(); 963 return createSolutionPerfomrance(); 964 } 965} 966 967function createSolutionPerfomrance(): SolutionPerformance { 968 let statistics: ESMap<string, Statistic> | undefined; 969 return { 970 addAggregateStatistic, 971 forEachAggregateStatistics: forEachAggreateStatistics, 972 clear, 973 }; 974 975 function addAggregateStatistic(s: Statistic) { 976 const existing = statistics?.get(s.name); 977 if (existing) { 978 if (existing.type === StatisticType.memory) existing.value = Math.max(existing.value, s.value); 979 else existing.value += s.value; 980 } 981 else { 982 (statistics ??= new Map()).set(s.name, s); 983 } 984 } 985 986 function forEachAggreateStatistics(cb: (s: Statistic) => void) { 987 statistics?.forEach(cb); 988 } 989 990 function clear() { 991 statistics = undefined; 992 } 993} 994 995function reportSolutionBuilderTimes( 996 builder: SolutionBuilder<EmitAndSemanticDiagnosticsBuilderProgram>, 997 solutionPerformance: SolutionPerformance | undefined) { 998 if (!solutionPerformance) return; 999 1000 if (!performance.isEnabled()) { 1001 sys.write(Diagnostics.Performance_timings_for_diagnostics_or_extendedDiagnostics_are_not_available_in_this_session_A_native_implementation_of_the_Web_Performance_API_could_not_be_found.message + "\n"); 1002 return; 1003 } 1004 1005 const statistics: Statistic[] = []; 1006 statistics.push( 1007 { name: "Projects in scope", value: getBuildOrderFromAnyBuildOrder(builder.getBuildOrder()).length, type: StatisticType.count }, 1008 ); 1009 reportSolutionBuilderCountStatistic("SolutionBuilder::Projects built"); 1010 reportSolutionBuilderCountStatistic("SolutionBuilder::Timestamps only updates"); 1011 reportSolutionBuilderCountStatistic("SolutionBuilder::Bundles updated"); 1012 solutionPerformance.forEachAggregateStatistics(s => { 1013 s.name = `Aggregate ${s.name}`; 1014 statistics.push(s); 1015 }); 1016 performance.forEachMeasure((name, duration) => { 1017 if (isSolutionMarkOrMeasure(name)) statistics.push({ name: `${getNameFromSolutionBuilderMarkOrMeasure(name)} time`, value: duration, type: StatisticType.time }); 1018 }); 1019 performance.disable(); 1020 performance.enable(); 1021 1022 reportAllStatistics(sys, statistics); 1023 1024 function reportSolutionBuilderCountStatistic(name: string) { 1025 const value = performance.getCount(name); 1026 if (value) { 1027 statistics.push({ name: getNameFromSolutionBuilderMarkOrMeasure(name), value, type: StatisticType.count }); 1028 } 1029 } 1030 1031 function getNameFromSolutionBuilderMarkOrMeasure(name: string) { 1032 return name.replace("SolutionBuilder::", ""); 1033 } 1034} 1035 1036function canReportDiagnostics(system: System, compilerOptions: CompilerOptions) { 1037 return system === sys && (compilerOptions.diagnostics || compilerOptions.extendedDiagnostics); 1038} 1039 1040function canTrace(system: System, compilerOptions: CompilerOptions) { 1041 return system === sys && compilerOptions.generateTrace; 1042} 1043 1044function enableStatisticsAndTracing(system: System, compilerOptions: CompilerOptions, isBuildMode: boolean) { 1045 if (canReportDiagnostics(system, compilerOptions)) { 1046 performance.enable(system); 1047 } 1048 1049 if (canTrace(system, compilerOptions)) { 1050 startTracing(isBuildMode ? "build" : "project", 1051 compilerOptions.generateTrace!, compilerOptions.configFilePath); 1052 } 1053} 1054 1055function isSolutionMarkOrMeasure(name: string) { 1056 return startsWith(name, "SolutionBuilder::"); 1057} 1058 1059function reportStatistics(sys: System, program: Program, solutionPerformance: SolutionPerformance | undefined) { 1060 const compilerOptions = program.getCompilerOptions(); 1061 1062 if (canTrace(sys, compilerOptions)) { 1063 tracing?.stopTracing(); 1064 } 1065 1066 let statistics: Statistic[]; 1067 if (canReportDiagnostics(sys, compilerOptions)) { 1068 statistics = []; 1069 const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1; 1070 reportCountStatistic("Files", program.getSourceFiles().length); 1071 1072 const lineCounts = countLines(program); 1073 if (compilerOptions.extendedDiagnostics) { 1074 for (const key of arrayFrom(lineCounts.keys())) { 1075 reportCountStatistic("Lines of " + key, lineCounts.get(key)!); 1076 } 1077 } 1078 else { 1079 reportCountStatistic("Lines", reduceLeftIterator(lineCounts.values(), (sum, count) => sum + count, 0)); 1080 } 1081 1082 reportCountStatistic("Identifiers", program.getIdentifierCount()); 1083 reportCountStatistic("Symbols", program.getSymbolCount()); 1084 reportCountStatistic("Types", program.getTypeCount()); 1085 reportCountStatistic("Instantiations", program.getInstantiationCount()); 1086 1087 if (memoryUsed >= 0) { 1088 reportStatisticalValue({ name: "Memory used", value: memoryUsed, type: StatisticType.memory }, /*aggregate*/ true); 1089 } 1090 1091 const isPerformanceEnabled = performance.isEnabled(); 1092 const programTime = isPerformanceEnabled ? performance.getDuration("Program") : 0; 1093 const bindTime = isPerformanceEnabled ? performance.getDuration("Bind") : 0; 1094 const checkTime = isPerformanceEnabled ? performance.getDuration("Check") : 0; 1095 const emitTime = isPerformanceEnabled ? performance.getDuration("Emit") : 0; 1096 if (compilerOptions.extendedDiagnostics) { 1097 const caches = program.getRelationCacheSizes(); 1098 reportCountStatistic("Assignability cache size", caches.assignable); 1099 reportCountStatistic("Identity cache size", caches.identity); 1100 reportCountStatistic("Subtype cache size", caches.subtype); 1101 reportCountStatistic("Strict subtype cache size", caches.strictSubtype); 1102 if (isPerformanceEnabled) { 1103 performance.forEachMeasure((name, duration) => { 1104 if (!isSolutionMarkOrMeasure(name)) reportTimeStatistic(`${name} time`, duration, /*aggregate*/ true); 1105 }); 1106 } 1107 } 1108 else if (isPerformanceEnabled) { 1109 // Individual component times. 1110 // Note: To match the behavior of previous versions of the compiler, the reported parse time includes 1111 // I/O read time and processing time for triple-slash references and module imports, and the reported 1112 // emit time includes I/O write time. We preserve this behavior so we can accurately compare times. 1113 reportTimeStatistic("I/O read", performance.getDuration("I/O Read"), /*aggregate*/ true); 1114 reportTimeStatistic("I/O write", performance.getDuration("I/O Write"), /*aggregate*/ true); 1115 reportTimeStatistic("Parse time", programTime, /*aggregate*/ true); 1116 reportTimeStatistic("Bind time", bindTime, /*aggregate*/ true); 1117 reportTimeStatistic("Check time", checkTime, /*aggregate*/ true); 1118 reportTimeStatistic("Emit time", emitTime, /*aggregate*/ true); 1119 } 1120 if (isPerformanceEnabled) { 1121 reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime, /*aggregate*/ false); 1122 } 1123 reportAllStatistics(sys, statistics); 1124 if (!isPerformanceEnabled) { 1125 sys.write(Diagnostics.Performance_timings_for_diagnostics_or_extendedDiagnostics_are_not_available_in_this_session_A_native_implementation_of_the_Web_Performance_API_could_not_be_found.message + "\n"); 1126 } 1127 else { 1128 if (solutionPerformance) { 1129 // Clear selected marks and measures 1130 performance.forEachMeasure(name => { 1131 if (!isSolutionMarkOrMeasure(name)) performance.clearMeasures(name); 1132 }); 1133 performance.forEachMark(name => { 1134 if (!isSolutionMarkOrMeasure(name)) performance.clearMarks(name); 1135 }); 1136 } 1137 else { 1138 performance.disable(); 1139 } 1140 } 1141 } 1142 1143 function reportStatisticalValue(s: Statistic, aggregate: boolean) { 1144 statistics.push(s); 1145 if (aggregate) solutionPerformance?.addAggregateStatistic(s); 1146 } 1147 1148 function reportCountStatistic(name: string, count: number) { 1149 reportStatisticalValue({ name, value: count, type: StatisticType.count }, /*aggregate*/ true); 1150 } 1151 1152 function reportTimeStatistic(name: string, time: number, aggregate: boolean) { 1153 reportStatisticalValue({ name, value: time, type: StatisticType.time }, aggregate); 1154 } 1155} 1156 1157function reportAllStatistics(sys: System, statistics: Statistic[]) { 1158 let nameSize = 0; 1159 let valueSize = 0; 1160 for (const s of statistics) { 1161 if (s.name.length > nameSize) { 1162 nameSize = s.name.length; 1163 } 1164 1165 const value = statisticValue(s); 1166 if (value.length > valueSize) { 1167 valueSize = value.length; 1168 } 1169 } 1170 1171 for (const s of statistics) { 1172 sys.write(padRight(s.name + ":", nameSize + 2) + padLeft(statisticValue(s).toString(), valueSize) + sys.newLine); 1173 } 1174} 1175 1176function statisticValue(s: Statistic) { 1177 switch (s.type) { 1178 case StatisticType.count: 1179 return "" + s.value; 1180 case StatisticType.time: 1181 return (s.value / 1000).toFixed(2) + "s"; 1182 case StatisticType.memory: 1183 return Math.round(s.value / 1000) + "K"; 1184 default: 1185 Debug.assertNever(s.type); 1186 } 1187} 1188 1189function writeConfigFile( 1190 sys: System, 1191 reportDiagnostic: DiagnosticReporter, 1192 options: CompilerOptions, 1193 fileNames: string[] 1194) { 1195 const currentDirectory = sys.getCurrentDirectory(); 1196 const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json")); 1197 if (sys.fileExists(file)) { 1198 reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file)); 1199 } 1200 else { 1201 sys.writeFile(file, generateTSConfig(options, fileNames, sys.newLine)); 1202 const output: string[] = [sys.newLine, ...getHeader(sys,"Created a new tsconfig.json with:")]; 1203 output.push(getCompilerOptionsDiffValue(options, sys.newLine) + sys.newLine + sys.newLine); 1204 output.push(`You can learn more at https://aka.ms/tsconfig` + sys.newLine); 1205 for (const line of output) { 1206 sys.write(line); 1207 } 1208 } 1209 1210 return; 1211} 1212