diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 01c4801b106..2371f771c94 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -290,23 +290,17 @@ namespace ts { } function getOutFileOutputs(project: ParsedCommandLine): ReadonlyArray { - const out = project.options.outFile || project.options.out; - if (!out) { - return Debug.fail("outFile must be set"); - } - const outputs: string[] = []; - outputs.push(out); - if (project.options.sourceMap) { - outputs.push(`${out}.map`); - } - if (getEmitDeclarations(project.options)) { - const dts = changeExtension(out, Extension.Dts); - outputs.push(dts); - if (project.options.declarationMap) { - outputs.push(`${dts}.map`); - } - } - return outputs; + Debug.assert(!!project.options.outFile || !!project.options.out, "outFile must be set"); + const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath } = getOutputPathsForBundle(project.options, /*forceDtsPaths*/ false); + + let outputs: string[] | undefined = []; + const addOutput = (path: string | undefined) => path && (outputs || (outputs = [])).push(path); + addOutput(jsFilePath); + addOutput(sourceMapFilePath); + addOutput(declarationFilePath); + addOutput(declarationMapPath); + addOutput(bundleInfoPath); + return outputs || emptyArray; } function rootDirOfOptions(opts: CompilerOptions, configFileName: string) { diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index 8c03e425902..fcccad423cf 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -466,6 +466,28 @@ export const b = new A();`); export namespace OutFile { const outFileFs = loadProjectFromDisk("tests/projects/outfile-concat"); + const outputFiles: [ReadonlyArray, ReadonlyArray, ReadonlyArray] = [ + [ + "/src/first/bin/first-output.js", + "/src/first/bin/first-output.js.map", + "/src/first/bin/first-output.d.ts", + "/src/first/bin/first-output.d.ts.map", + "/src/first/bin/first-output.tsbundleinfo" + ], + [ + "/src/2/second-output.js", + "/src/2/second-output.js.map", + "/src/2/second-output.d.ts", + "/src/2/second-output.d.ts.map", + "/src/2/second-output.tsbundleinfo" + ], + [ + "/src/third/thirdjs/output/third-output.js", + "/src/third/thirdjs/output/third-output.js.map", + "/src/third/thirdjs/output/third-output.d.ts", + "/src/third/thirdjs/output/third-output.d.ts.map" + ] + ]; function verifyOutFileScenario(scenario: string, modifyFs: (fs: vfs.FileSystem) => void | ReadonlyArray) { describe(`unittests:: tsbuild - outFile:: ${scenario}`, () => { @@ -528,16 +550,8 @@ export const b = new A();`); ...(additionalSourceFiles || emptyArray), // outputs - "/src/first/bin/first-output.js", - "/src/first/bin/first-output.js.map", - "/src/first/bin/first-output.d.ts", - "/src/first/bin/first-output.d.ts.map", - "/src/first/bin/first-output.tsbundleinfo", - "/src/2/second-output.js", - "/src/2/second-output.js.map", - "/src/2/second-output.d.ts", - "/src/2/second-output.d.ts.map", - "/src/2/second-output.tsbundleinfo", + ...outputFiles[0], + ...outputFiles[1] ]; assert.equal(actualReadFileMap.size, expected.length, `Expected: ${JSON.stringify(expected)} \nActual: ${JSON.stringify(arrayFrom(actualReadFileMap.entries()))}`); @@ -567,6 +581,31 @@ export const b = new A();`); assert.equal(fs.statSync("src/third/thirdjs/output/third-output.js").mtimeMs, time(), "Second build timestamp is correct"); }); + it("unittests:: tsbuild - outFile:: clean projects", () => { + const fs = outFileFs.shadow(); + const expectedOutputs = [ + ...outputFiles[0], + ...outputFiles[1], + ...outputFiles[2] + ]; + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: false }); + builder.buildAllProjects(); + host.assertDiagnosticMessages(/*none*/); + // Verify they exist + for (const output of expectedOutputs) { + assert(fs.existsSync(output), `Expect file ${output} to exist`); + } + builder.cleanAllProjects(); + host.assertDiagnosticMessages(/*none*/); + // Verify they are gone + for (const output of expectedOutputs) { + assert(!fs.existsSync(output), `Expect file ${output} to not exist`); + } + // Subsequent clean shouldn't throw / etc + builder.cleanAllProjects(); + }); + function replaceFileContent(fs: vfs.FileSystem, path: string, searchValue: string, replaceValue: string) { const content = fs.readFileSync(path, "utf8"); fs.writeFileSync(path, content.replace(searchValue, replaceValue));