From e430f2a81cafb3fe31a32c42321c769a3d084056 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 18 Sep 2019 14:02:41 -0700 Subject: [PATCH] Add output file names api for supporting ts-loader --- src/compiler/builder.ts | 4 +- src/compiler/emitter.ts | 90 +++++++++++++------ src/compiler/program.ts | 4 +- src/compiler/tsbuild.ts | 2 +- src/compiler/watch.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 2 + tests/baselines/reference/api/typescript.d.ts | 2 + 7 files changed, 71 insertions(+), 35 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 653832c8dbde7..a67a6a246ccba 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -257,7 +257,7 @@ namespace ts { function convertToDiagnostics(diagnostics: readonly ReusableDiagnostic[], newProgram: Program, getCanonicalFileName: GetCanonicalFileName): readonly Diagnostic[] { if (!diagnostics.length) return emptyArray; - const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getOutputPathForBuildInfo(newProgram.getCompilerOptions())!, newProgram.getCurrentDirectory())); + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(newProgram.getCompilerOptions())!, newProgram.getCurrentDirectory())); return diagnostics.map(diagnostic => { const result: Diagnostic = convertToDiagnosticRelatedInformation(diagnostic, newProgram, toPath); result.reportsUnnecessary = diagnostic.reportsUnnecessary; @@ -656,7 +656,7 @@ namespace ts { function getProgramBuildInfo(state: Readonly, getCanonicalFileName: GetCanonicalFileName): ProgramBuildInfo | undefined { if (state.compilerOptions.outFile || state.compilerOptions.out) return undefined; const currentDirectory = Debug.assertDefined(state.program).getCurrentDirectory(); - const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getOutputPathForBuildInfo(state.compilerOptions)!, currentDirectory)); + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory)); const fileInfos: MapLike = {}; state.fileInfos.forEach((value, key) => { const signature = state.currentAffectedFilesSignatures && state.currentAffectedFilesSignatures.get(key); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 91df5402be3f2..7bad8359b26ee 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -45,14 +45,13 @@ namespace ts { } } if (includeBuildInfo) { - const buildInfoPath = getOutputPathForBuildInfo(host.getCompilerOptions()); + const buildInfoPath = getTsBuildInfoEmitOutputFilePath(host.getCompilerOptions()); if (buildInfoPath) return action({ buildInfoPath }, /*sourceFileOrBundle*/ undefined); } } } - /*@internal*/ - export function getOutputPathForBuildInfo(options: CompilerOptions) { + export function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions) { const configFile = options.configFilePath; if (!isIncrementalCompilation(options)) return undefined; if (options.tsBuildInfoFile) return options.tsBuildInfoFile; @@ -80,7 +79,7 @@ namespace ts { const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options); const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? removeFileExtension(outPath) + Extension.Dts : undefined; const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; - const buildInfoPath = getOutputPathForBuildInfo(options); + const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options); return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }; } @@ -170,38 +169,71 @@ namespace ts { undefined; } + function createAddOutput() { + let outputs: string[] | undefined; + return { addOutput, getOutputs }; + function addOutput(path: string | undefined) { + if (path) { + (outputs || (outputs = [])).push(path); + } + } + function getOutputs(): readonly string[] { + return outputs || emptyArray; + } + } + + function getSingleOutputFileNames(configFile: ParsedCommandLine, addOutput: ReturnType["addOutput"]) { + const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false); + addOutput(jsFilePath); + addOutput(sourceMapFilePath); + addOutput(declarationFilePath); + addOutput(declarationMapPath); + addOutput(buildInfoPath); + } + + function getOwnOutputFileNames(configFile: ParsedCommandLine, inputFileName: string, ignoreCase: boolean, addOutput: ReturnType["addOutput"]) { + if (fileExtensionIs(inputFileName, Extension.Dts)) return; + const js = getOutputJSFileName(inputFileName, configFile, ignoreCase); + addOutput(js); + if (fileExtensionIs(inputFileName, Extension.Json)) return; + if (js && configFile.options.sourceMap) { + addOutput(`${js}.map`); + } + if (getEmitDeclarations(configFile.options) && hasTSFileExtension(inputFileName)) { + const dts = getOutputDeclarationFileName(inputFileName, configFile, ignoreCase); + addOutput(dts); + if (configFile.options.declarationMap) { + addOutput(`${dts}.map`); + } + } + } + /*@internal*/ export function getAllProjectOutputs(configFile: ParsedCommandLine, ignoreCase: boolean): readonly string[] { - let outputs: string[] | undefined; - const addOutput = (path: string | undefined) => path && (outputs || (outputs = [])).push(path); + const { addOutput, getOutputs } = createAddOutput(); if (configFile.options.outFile || configFile.options.out) { - const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false); - addOutput(jsFilePath); - addOutput(sourceMapFilePath); - addOutput(declarationFilePath); - addOutput(declarationMapPath); - addOutput(buildInfoPath); + getSingleOutputFileNames(configFile, addOutput); } else { for (const inputFileName of configFile.fileNames) { - if (fileExtensionIs(inputFileName, Extension.Dts)) continue; - const js = getOutputJSFileName(inputFileName, configFile, ignoreCase); - addOutput(js); - if (fileExtensionIs(inputFileName, Extension.Json)) continue; - if (js && configFile.options.sourceMap) { - addOutput(`${js}.map`); - } - if (getEmitDeclarations(configFile.options) && hasTSFileExtension(inputFileName)) { - const dts = getOutputDeclarationFileName(inputFileName, configFile, ignoreCase); - addOutput(dts); - if (configFile.options.declarationMap) { - addOutput(`${dts}.map`); - } - } + getOwnOutputFileNames(configFile, inputFileName, ignoreCase, addOutput); } - addOutput(getOutputPathForBuildInfo(configFile.options)); + addOutput(getTsBuildInfoEmitOutputFilePath(configFile.options)); + } + return getOutputs(); + } + + export function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[] { + inputFileName = normalizePath(inputFileName); + Debug.assert(contains(commandLine.fileNames, inputFileName), `Expected fileName to be present in command line`); + const { addOutput, getOutputs } = createAddOutput(); + if (commandLine.options.outFile || commandLine.options.out) { + getSingleOutputFileNames(commandLine, addOutput); + } + else { + getOwnOutputFileNames(commandLine, inputFileName, ignoreCase, addOutput); } - return outputs || emptyArray; + return getOutputs(); } /*@internal*/ @@ -220,7 +252,7 @@ namespace ts { return getOutputDeclarationFileName(inputFileName, configFile, ignoreCase); } } - const buildInfoPath = getOutputPathForBuildInfo(configFile.options); + const buildInfoPath = getTsBuildInfoEmitOutputFilePath(configFile.options); if (buildInfoPath) return buildInfoPath; return Debug.fail(`project ${configFile.options.configFilePath} expected to have at least one output`); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 68eccdff30726..427ab577bf31b 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -3108,7 +3108,7 @@ namespace ts { } function verifyProjectReferences() { - const buildInfoPath = !options.noEmit && !options.suppressOutputPathCheck ? getOutputPathForBuildInfo(options) : undefined; + const buildInfoPath = !options.noEmit && !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined; forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, index, parent) => { const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index]; const parentFile = parent && parent.sourceFile as JsonSourceFile; @@ -3135,7 +3135,7 @@ namespace ts { createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, ref.path); } } - if (!parent && buildInfoPath && buildInfoPath === getOutputPathForBuildInfo(options)) { + if (!parent && buildInfoPath && buildInfoPath === getTsBuildInfoEmitOutputFilePath(options)) { createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_write_file_0_because_it_will_overwrite_tsbuildinfo_file_generated_by_referenced_project_1, buildInfoPath, ref.path); hasEmitBlockingDiagnostics.set(toPath(buildInfoPath), true); } diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index d572fc9dad8d9..69b90135fd056 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -1621,7 +1621,7 @@ namespace ts { if (!state.buildInfoChecked.has(resolvedPath)) { state.buildInfoChecked.set(resolvedPath, true); - const buildInfoPath = getOutputPathForBuildInfo(project.options); + const buildInfoPath = getTsBuildInfoEmitOutputFilePath(project.options); if (buildInfoPath) { const value = state.readFileWithCache(buildInfoPath); const buildInfo = value && getBuildInfo(value); diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index b3b4739a2c62f..652b85d000d50 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -447,7 +447,7 @@ namespace ts { } export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost) { if (compilerOptions.out || compilerOptions.outFile) return undefined; - const buildInfoPath = getOutputPathForBuildInfo(compilerOptions); + const buildInfoPath = getTsBuildInfoEmitOutputFilePath(compilerOptions); if (!buildInfoPath) return undefined; const content = host.readFile(buildInfoPath); if (!content) return undefined; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 58d513b2e0a4b..79450ca83c9d3 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4289,6 +4289,8 @@ declare namespace ts { function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; } declare namespace ts { + function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions): string | undefined; + function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[]; function createPrinter(printerOptions?: PrinterOptions, handlers?: PrintHandlers): Printer; } declare namespace ts { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index bc71eaffa373f..f0ae718d57001 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4289,6 +4289,8 @@ declare namespace ts { function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; } declare namespace ts { + function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions): string | undefined; + function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[]; function createPrinter(printerOptions?: PrinterOptions, handlers?: PrintHandlers): Printer; } declare namespace ts {