mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-13 04:57:55 -06:00
Handle output file names descripency between tsc --b and actual program emit file path calculation (#41811)
* Baseline showing #41801 and other issues with output path calculation * Add a way to note descripencies between clean and incremental build * Add descripency when no rootDir is specified but project is composite * if rootDir is specified, irrespective of whether all files belong to rootDir, the paths should be calculated from rootDir * Fix the output file names api to use the correct common source directory * Tests for #41780 * Spelling
This commit is contained in:
parent
37e898cfd7
commit
bfb259128b
@ -130,36 +130,32 @@ namespace ts {
|
||||
return Extension.Js;
|
||||
}
|
||||
|
||||
function rootDirOfOptions(configFile: ParsedCommandLine) {
|
||||
return configFile.options.rootDir || getDirectoryPath(Debug.checkDefined(configFile.options.configFilePath));
|
||||
}
|
||||
|
||||
function getOutputPathWithoutChangingExt(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, outputDir: string | undefined) {
|
||||
function getOutputPathWithoutChangingExt(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, outputDir: string | undefined, getCommonSourceDirectory?: () => string) {
|
||||
return outputDir ?
|
||||
resolvePath(
|
||||
outputDir,
|
||||
getRelativePathFromDirectory(rootDirOfOptions(configFile), inputFileName, ignoreCase)
|
||||
getRelativePathFromDirectory(getCommonSourceDirectory ? getCommonSourceDirectory() : getCommonSourceDirectoryOfConfig(configFile, ignoreCase), inputFileName, ignoreCase)
|
||||
) :
|
||||
inputFileName;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean) {
|
||||
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory?: () => string) {
|
||||
Debug.assert(!fileExtensionIs(inputFileName, Extension.Dts) && !fileExtensionIs(inputFileName, Extension.Json));
|
||||
return changeExtension(
|
||||
getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.declarationDir || configFile.options.outDir),
|
||||
getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.declarationDir || configFile.options.outDir, getCommonSourceDirectory),
|
||||
Extension.Dts
|
||||
);
|
||||
}
|
||||
|
||||
function getOutputJSFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean) {
|
||||
function getOutputJSFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory?: () => string) {
|
||||
if (configFile.options.emitDeclarationOnly) return undefined;
|
||||
const isJsonFile = fileExtensionIs(inputFileName, Extension.Json);
|
||||
const outputFileName = changeExtension(
|
||||
getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.outDir),
|
||||
getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.outDir, getCommonSourceDirectory),
|
||||
isJsonFile ?
|
||||
Extension.Json :
|
||||
fileExtensionIs(inputFileName, Extension.Tsx) && configFile.options.jsx === JsxEmit.Preserve ?
|
||||
configFile.options.jsx === JsxEmit.Preserve && (fileExtensionIs(inputFileName, Extension.Tsx) || fileExtensionIs(inputFileName, Extension.Jsx)) ?
|
||||
Extension.Jsx :
|
||||
Extension.Js
|
||||
);
|
||||
@ -190,16 +186,16 @@ namespace ts {
|
||||
addOutput(buildInfoPath);
|
||||
}
|
||||
|
||||
function getOwnOutputFileNames(configFile: ParsedCommandLine, inputFileName: string, ignoreCase: boolean, addOutput: ReturnType<typeof createAddOutput>["addOutput"]) {
|
||||
function getOwnOutputFileNames(configFile: ParsedCommandLine, inputFileName: string, ignoreCase: boolean, addOutput: ReturnType<typeof createAddOutput>["addOutput"], getCommonSourceDirectory?: () => string) {
|
||||
if (fileExtensionIs(inputFileName, Extension.Dts)) return;
|
||||
const js = getOutputJSFileName(inputFileName, configFile, ignoreCase);
|
||||
const js = getOutputJSFileName(inputFileName, configFile, ignoreCase, getCommonSourceDirectory);
|
||||
addOutput(js);
|
||||
if (fileExtensionIs(inputFileName, Extension.Json)) return;
|
||||
if (js && configFile.options.sourceMap) {
|
||||
addOutput(`${js}.map`);
|
||||
}
|
||||
if (getEmitDeclarations(configFile.options)) {
|
||||
const dts = getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
|
||||
const dts = getOutputDeclarationFileName(inputFileName, configFile, ignoreCase, getCommonSourceDirectory);
|
||||
addOutput(dts);
|
||||
if (configFile.options.declarationMap) {
|
||||
addOutput(`${dts}.map`);
|
||||
@ -207,6 +203,48 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function getCommonSourceDirectory(
|
||||
options: CompilerOptions,
|
||||
emittedFiles: () => readonly string[],
|
||||
currentDirectory: string,
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
checkSourceFilesBelongToPath?: (commonSourceDirectory: string) => void
|
||||
): string {
|
||||
let commonSourceDirectory;
|
||||
if (options.rootDir) {
|
||||
// If a rootDir is specified use it as the commonSourceDirectory
|
||||
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
|
||||
checkSourceFilesBelongToPath?.(options.rootDir);
|
||||
}
|
||||
else if (options.composite && options.configFilePath) {
|
||||
// Project compilations never infer their root from the input source paths
|
||||
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath));
|
||||
checkSourceFilesBelongToPath?.(commonSourceDirectory);
|
||||
}
|
||||
else {
|
||||
commonSourceDirectory = computeCommonSourceDirectoryOfFilenames(emittedFiles(), currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) {
|
||||
// Make sure directory path ends with directory separator so this string can directly
|
||||
// used to replace with "" to get the relative path of the source file and the relative path doesn't
|
||||
// start with / making it rooted path
|
||||
commonSourceDirectory += directorySeparator;
|
||||
}
|
||||
return commonSourceDirectory;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function getCommonSourceDirectoryOfConfig({ options, fileNames }: ParsedCommandLine, ignoreCase: boolean): string {
|
||||
return getCommonSourceDirectory(
|
||||
options,
|
||||
() => filter(fileNames, file => !(options.noEmitForJsFiles && fileExtensionIsOneOf(file, supportedJSExtensions)) && !fileExtensionIs(file, Extension.Dts)),
|
||||
getDirectoryPath(normalizeSlashes(Debug.checkDefined(options.configFilePath))),
|
||||
createGetCanonicalFileName(!ignoreCase)
|
||||
);
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function getAllProjectOutputs(configFile: ParsedCommandLine, ignoreCase: boolean): readonly string[] {
|
||||
const { addOutput, getOutputs } = createAddOutput();
|
||||
@ -214,8 +252,9 @@ namespace ts {
|
||||
getSingleOutputFileNames(configFile, addOutput);
|
||||
}
|
||||
else {
|
||||
const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(configFile, ignoreCase));
|
||||
for (const inputFileName of configFile.fileNames) {
|
||||
getOwnOutputFileNames(configFile, inputFileName, ignoreCase, addOutput);
|
||||
getOwnOutputFileNames(configFile, inputFileName, ignoreCase, addOutput, getCommonSourceDirectory);
|
||||
}
|
||||
addOutput(getTsBuildInfoEmitOutputFilePath(configFile.options));
|
||||
}
|
||||
@ -242,13 +281,14 @@ namespace ts {
|
||||
return Debug.checkDefined(jsFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`);
|
||||
}
|
||||
|
||||
const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(configFile, ignoreCase));
|
||||
for (const inputFileName of configFile.fileNames) {
|
||||
if (fileExtensionIs(inputFileName, Extension.Dts)) continue;
|
||||
const jsFilePath = getOutputJSFileName(inputFileName, configFile, ignoreCase);
|
||||
const jsFilePath = getOutputJSFileName(inputFileName, configFile, ignoreCase, getCommonSourceDirectory);
|
||||
if (jsFilePath) return jsFilePath;
|
||||
if (fileExtensionIs(inputFileName, Extension.Json)) continue;
|
||||
if (getEmitDeclarations(configFile.options)) {
|
||||
return getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
|
||||
return getOutputDeclarationFileName(inputFileName, configFile, ignoreCase, getCommonSourceDirectory);
|
||||
}
|
||||
}
|
||||
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(configFile.options);
|
||||
|
||||
@ -13,7 +13,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function computeCommonSourceDirectoryOfFilenames(fileNames: string[], currentDirectory: string, getCanonicalFileName: GetCanonicalFileName): string {
|
||||
export function computeCommonSourceDirectoryOfFilenames(fileNames: readonly string[], currentDirectory: string, getCanonicalFileName: GetCanonicalFileName): string {
|
||||
let commonPathComponents: string[] | undefined;
|
||||
const failed = forEach(fileNames, sourceFile => {
|
||||
// Each file contributes into common source file path
|
||||
@ -899,9 +899,15 @@ namespace ts {
|
||||
processSourceFile(changeExtension(out, ".d.ts"), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
|
||||
const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(parsedRef.commandLine, !host.useCaseSensitiveFileNames()));
|
||||
for (const fileName of parsedRef.commandLine.fileNames) {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts) && !fileExtensionIs(fileName, Extension.Json)) {
|
||||
processSourceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames()), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
processSourceFile(
|
||||
getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory),
|
||||
/*isDefaultLib*/ false,
|
||||
/*ignoreNoDefaultLib*/ false,
|
||||
/*packageId*/ undefined
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1127,25 +1133,13 @@ namespace ts {
|
||||
function getCommonSourceDirectory() {
|
||||
if (commonSourceDirectory === undefined) {
|
||||
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, program));
|
||||
if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) {
|
||||
// If a rootDir is specified use it as the commonSourceDirectory
|
||||
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
|
||||
}
|
||||
else if (options.composite && options.configFilePath) {
|
||||
// Project compilations never infer their root from the input source paths
|
||||
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath));
|
||||
checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory);
|
||||
}
|
||||
else {
|
||||
commonSourceDirectory = computeCommonSourceDirectory(emittedFiles);
|
||||
}
|
||||
|
||||
if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) {
|
||||
// Make sure directory path ends with directory separator so this string can directly
|
||||
// used to replace with "" to get the relative path of the source file and the relative path doesn't
|
||||
// start with / making it rooted path
|
||||
commonSourceDirectory += directorySeparator;
|
||||
}
|
||||
commonSourceDirectory = ts.getCommonSourceDirectory(
|
||||
options,
|
||||
() => mapDefined(emittedFiles, file => file.isDeclarationFile ? undefined : file.fileName),
|
||||
currentDirectory,
|
||||
getCanonicalFileName,
|
||||
commonSourceDirectory => checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory)
|
||||
);
|
||||
}
|
||||
return commonSourceDirectory;
|
||||
}
|
||||
@ -2707,9 +2701,10 @@ namespace ts {
|
||||
mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), true);
|
||||
}
|
||||
else {
|
||||
const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(resolvedRef.commandLine, !host.useCaseSensitiveFileNames()));
|
||||
forEach(resolvedRef.commandLine.fileNames, fileName => {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts) && !fileExtensionIs(fileName, Extension.Json)) {
|
||||
const outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, host.useCaseSensitiveFileNames());
|
||||
const outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory);
|
||||
mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), fileName);
|
||||
}
|
||||
});
|
||||
@ -2973,11 +2968,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function computeCommonSourceDirectory(sourceFiles: SourceFile[]): string {
|
||||
const fileNames = mapDefined(sourceFiles, file => file.isDeclarationFile ? undefined : file.fileName);
|
||||
return computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
function checkSourceFilesBelongToPath(sourceFiles: readonly SourceFile[], rootDirectory: string): boolean {
|
||||
let allFilesBelongToPath = true;
|
||||
const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory));
|
||||
|
||||
@ -125,6 +125,7 @@
|
||||
"unittests/tsbuild/moduleSpecifiers.ts",
|
||||
"unittests/tsbuild/noEmitOnError.ts",
|
||||
"unittests/tsbuild/outFile.ts",
|
||||
"unittests/tsbuild/outputPaths.ts",
|
||||
"unittests/tsbuild/referencesWithRootDirInParent.ts",
|
||||
"unittests/tsbuild/resolveJsonModule.ts",
|
||||
"unittests/tsbuild/sample.ts",
|
||||
|
||||
@ -270,11 +270,12 @@ interface Symbol {
|
||||
tick: () => void;
|
||||
baseFs: vfs.FileSystem;
|
||||
newSys: TscCompileSystem;
|
||||
cleanBuildDiscrepancies: TscIncremental["cleanBuildDiscrepancies"];
|
||||
}
|
||||
function verifyIncrementalCorrectness(input: () => VerifyIncrementalCorrectness, index: number) {
|
||||
it(`Verify emit output file text is same when built clean for incremental scenario at:: ${index}`, () => {
|
||||
const {
|
||||
scenario, subScenario, commandLineArgs,
|
||||
scenario, subScenario, commandLineArgs, cleanBuildDiscrepancies,
|
||||
modifyFs, incrementalModifyFs,
|
||||
tick, baseFs, newSys
|
||||
} = input();
|
||||
@ -289,54 +290,82 @@ interface Symbol {
|
||||
incrementalModifyFs(fs);
|
||||
},
|
||||
});
|
||||
const discrepancies = cleanBuildDiscrepancies?.();
|
||||
for (const outputFile of arrayFrom(sys.writtenFiles.keys())) {
|
||||
const expectedText = sys.readFile(outputFile);
|
||||
const actualText = newSys.readFile(outputFile);
|
||||
const cleanBuildText = sys.readFile(outputFile);
|
||||
const incrementalBuildText = newSys.readFile(outputFile);
|
||||
const descrepancyInClean = discrepancies?.get(outputFile);
|
||||
if (!isBuildInfoFile(outputFile)) {
|
||||
assert.equal(actualText, expectedText, `File: ${outputFile}`);
|
||||
verifyTextEqual(incrementalBuildText, cleanBuildText, descrepancyInClean, `File: ${outputFile}`);
|
||||
}
|
||||
else if (actualText !== expectedText) {
|
||||
else if (incrementalBuildText !== cleanBuildText) {
|
||||
// Verify build info without affectedFilesPendingEmit
|
||||
const { buildInfo: actualBuildInfo, affectedFilesPendingEmit: actualAffectedFilesPendingEmit } = getBuildInfoForIncrementalCorrectnessCheck(actualText);
|
||||
const { buildInfo: expectedBuildInfo, affectedFilesPendingEmit: expectedAffectedFilesPendingEmit } = getBuildInfoForIncrementalCorrectnessCheck(expectedText);
|
||||
assert.deepEqual(actualBuildInfo, expectedBuildInfo, `TsBuild info text without affectedFilesPendingEmit: ${outputFile}::\nIncremental buildInfoText:: ${actualText}\nClean buildInfoText:: ${expectedText}`);
|
||||
const { buildInfo: incrementalBuildInfo, affectedFilesPendingEmit: incrementalBuildAffectedFilesPendingEmit } = getBuildInfoForIncrementalCorrectnessCheck(incrementalBuildText);
|
||||
const { buildInfo: cleanBuildInfo, affectedFilesPendingEmit: incrementalAffectedFilesPendingEmit } = getBuildInfoForIncrementalCorrectnessCheck(cleanBuildText);
|
||||
verifyTextEqual(incrementalBuildInfo, cleanBuildInfo, descrepancyInClean, `TsBuild info text without affectedFilesPendingEmit ${subScenario}:: ${outputFile}::\nIncremental buildInfoText:: ${incrementalBuildText}\nClean buildInfoText:: ${cleanBuildText}`);
|
||||
// Verify that incrementally pending affected file emit are in clean build since clean build can contain more files compared to incremental depending of noEmitOnError option
|
||||
if (actualAffectedFilesPendingEmit) {
|
||||
assert.isDefined(expectedAffectedFilesPendingEmit, `Incremental build contains affectedFilesPendingEmit, clean build should also have it: ${outputFile}::\nIncremental buildInfoText:: ${actualText}\nClean buildInfoText:: ${expectedText}`);
|
||||
if (incrementalBuildAffectedFilesPendingEmit && descrepancyInClean === undefined) {
|
||||
assert.isDefined(incrementalAffectedFilesPendingEmit, `Incremental build contains affectedFilesPendingEmit, clean build should also have it: ${outputFile}::\nIncremental buildInfoText:: ${incrementalBuildText}\nClean buildInfoText:: ${cleanBuildText}`);
|
||||
let expectedIndex = 0;
|
||||
actualAffectedFilesPendingEmit.forEach(([actualFile]) => {
|
||||
expectedIndex = findIndex(expectedAffectedFilesPendingEmit!, ([expectedFile]) => actualFile === expectedFile, expectedIndex);
|
||||
assert.notEqual(expectedIndex, -1, `Incremental build contains ${actualFile} file as pending emit, clean build should also have it: ${outputFile}::\nIncremental buildInfoText:: ${actualText}\nClean buildInfoText:: ${expectedText}`);
|
||||
incrementalBuildAffectedFilesPendingEmit.forEach(([actualFile]) => {
|
||||
expectedIndex = findIndex(incrementalAffectedFilesPendingEmit!, ([expectedFile]) => actualFile === expectedFile, expectedIndex);
|
||||
assert.notEqual(expectedIndex, -1, `Incremental build contains ${actualFile} file as pending emit, clean build should also have it: ${outputFile}::\nIncremental buildInfoText:: ${incrementalBuildText}\nClean buildInfoText:: ${cleanBuildText}`);
|
||||
expectedIndex++;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function verifyTextEqual(incrementalText: string | undefined, cleanText: string | undefined, descrepancyInClean: CleanBuildDescrepancy | undefined, message: string) {
|
||||
if (descrepancyInClean === undefined) {
|
||||
assert.equal(incrementalText, cleanText, message);
|
||||
return;
|
||||
}
|
||||
switch (descrepancyInClean) {
|
||||
case CleanBuildDescrepancy.CleanFileTextDifferent:
|
||||
assert.isDefined(incrementalText, `Incremental file should be present:: ${message}`);
|
||||
assert.isDefined(cleanText, `Clean file should be present present:: ${message}`);
|
||||
assert.notEqual(incrementalText, cleanText, message);
|
||||
return;
|
||||
case CleanBuildDescrepancy.CleanFilePresent:
|
||||
assert.isUndefined(incrementalText, `Incremental file should be absent:: ${message}`);
|
||||
assert.isDefined(cleanText, `Clean file should be present:: ${message}`);
|
||||
return;
|
||||
default:
|
||||
Debug.assertNever(descrepancyInClean);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getBuildInfoForIncrementalCorrectnessCheck(text: string | undefined): { buildInfo: BuildInfo | undefined; affectedFilesPendingEmit?: ProgramBuildInfo["affectedFilesPendingEmit"]; } {
|
||||
function getBuildInfoForIncrementalCorrectnessCheck(text: string | undefined): { buildInfo: string | undefined; affectedFilesPendingEmit?: ProgramBuildInfo["affectedFilesPendingEmit"]; } {
|
||||
const buildInfo = text ? getBuildInfo(text) : undefined;
|
||||
if (!buildInfo?.program) return { buildInfo };
|
||||
if (!buildInfo?.program) return { buildInfo: text };
|
||||
// Ignore noEmit since that shouldnt be reason to emit the tsbuild info and presence of it in the buildinfo file does not matter
|
||||
const { program: { affectedFilesPendingEmit, options: { noEmit, ...optionsRest}, ...programRest }, ...rest } = buildInfo;
|
||||
return {
|
||||
buildInfo: {
|
||||
buildInfo: getBuildInfoText({
|
||||
...rest,
|
||||
program: {
|
||||
options: optionsRest,
|
||||
...programRest
|
||||
}
|
||||
},
|
||||
}),
|
||||
affectedFilesPendingEmit
|
||||
};
|
||||
}
|
||||
|
||||
export enum CleanBuildDescrepancy {
|
||||
CleanFileTextDifferent,
|
||||
CleanFilePresent,
|
||||
}
|
||||
|
||||
export interface TscIncremental {
|
||||
buildKind: BuildKind;
|
||||
modifyFs: (fs: vfs.FileSystem) => void;
|
||||
subScenario?: string;
|
||||
commandLineArgs?: readonly string[];
|
||||
cleanBuildDiscrepancies?: () => ESMap<string, CleanBuildDescrepancy>;
|
||||
}
|
||||
|
||||
export interface VerifyTsBuildInput extends VerifyTsBuildInputWorker {
|
||||
@ -396,7 +425,8 @@ interface Symbol {
|
||||
buildKind,
|
||||
modifyFs: incrementalModifyFs,
|
||||
subScenario: incrementalSubScenario,
|
||||
commandLineArgs: incrementalCommandLineArgs
|
||||
commandLineArgs: incrementalCommandLineArgs,
|
||||
cleanBuildDiscrepancies,
|
||||
}, index) => {
|
||||
describe(incrementalSubScenario || buildKind, () => {
|
||||
let newSys: TscCompileSystem;
|
||||
@ -425,10 +455,11 @@ interface Symbol {
|
||||
verifyTscBaseline(() => newSys);
|
||||
verifyIncrementalCorrectness(() => ({
|
||||
scenario,
|
||||
subScenario,
|
||||
subScenario: incrementalSubScenario || subScenario,
|
||||
baseFs,
|
||||
newSys,
|
||||
commandLineArgs: incrementalCommandLineArgs || commandLineArgs,
|
||||
cleanBuildDiscrepancies,
|
||||
incrementalModifyFs,
|
||||
modifyFs,
|
||||
tick
|
||||
@ -520,12 +551,13 @@ interface Symbol {
|
||||
}));
|
||||
});
|
||||
describe("incremental correctness", () => {
|
||||
incrementalScenarios.forEach(({ commandLineArgs: incrementalCommandLineArgs }, index) => verifyIncrementalCorrectness(() => ({
|
||||
incrementalScenarios.forEach(({ commandLineArgs: incrementalCommandLineArgs, subScenario, buildKind, cleanBuildDiscrepancies }, index) => verifyIncrementalCorrectness(() => ({
|
||||
scenario,
|
||||
subScenario,
|
||||
subScenario: subScenario || buildKind,
|
||||
baseFs,
|
||||
newSys: incrementalSys[index],
|
||||
commandLineArgs: incrementalCommandLineArgs || commandLineArgs,
|
||||
cleanBuildDiscrepancies,
|
||||
incrementalModifyFs: fs => {
|
||||
for (let i = 0; i <= index; i++) {
|
||||
incrementalScenarios[i].modifyFs(fs);
|
||||
|
||||
117
src/testRunner/unittests/tsbuild/outputPaths.ts
Normal file
117
src/testRunner/unittests/tsbuild/outputPaths.ts
Normal file
@ -0,0 +1,117 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild - output file paths", () => {
|
||||
const noChangeProject: TscIncremental = {
|
||||
buildKind: BuildKind.NoChangeRun,
|
||||
modifyFs: noop,
|
||||
subScenario: "Normal build without change, that does not block emit on error to show files that get emitted",
|
||||
commandLineArgs: ["-p", "/src/tsconfig.json"],
|
||||
};
|
||||
const incrementalScenarios: TscIncremental[] = [
|
||||
noChangeRun,
|
||||
noChangeProject,
|
||||
];
|
||||
|
||||
function verify(input: Pick<VerifyTsBuildInput, "subScenario" | "fs" | "incrementalScenarios">, expectedOuptutNames: readonly string[]) {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
scenario: "outputPaths",
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "-v"],
|
||||
...input
|
||||
});
|
||||
|
||||
it("verify getOutputFileNames", () => {
|
||||
const sys = new fakes.System(input.fs().makeReadonly(), { executingFilePath: "/lib/tsc" }) as TscCompileSystem;
|
||||
;
|
||||
assert.deepEqual(
|
||||
getOutputFileNames(
|
||||
parseConfigFileWithSystem("/src/tsconfig.json", {}, {}, sys, noop)!,
|
||||
"/src/src/index.ts",
|
||||
/*ignoreCase*/ false
|
||||
),
|
||||
expectedOuptutNames
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is not specified",
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/tsconfig.json": JSON.stringify({
|
||||
compilerOptions: {
|
||||
outDir: "dist"
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios,
|
||||
}, ["/src/dist/index.js"]);
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is not specified and is composite",
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/tsconfig.json": JSON.stringify({
|
||||
compilerOptions: {
|
||||
outDir: "dist",
|
||||
composite: true
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios: [
|
||||
noChangeRun,
|
||||
{
|
||||
...noChangeProject,
|
||||
cleanBuildDiscrepancies: () => {
|
||||
const map = new Map<string, CleanBuildDescrepancy>();
|
||||
map.set("/src/dist/tsconfig.tsbuildinfo", CleanBuildDescrepancy.CleanFileTextDifferent); // tsbuildinfo will have -p setting when built using -p vs no build happens incrementally because of no change.
|
||||
return map;
|
||||
}
|
||||
}
|
||||
],
|
||||
}, ["/src/dist/src/index.js", "/src/dist/src/index.d.ts"]);
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is specified",
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/tsconfig.json": JSON.stringify({
|
||||
compilerOptions: {
|
||||
outDir: "dist",
|
||||
rootDir: "src"
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios,
|
||||
}, ["/src/dist/index.js"]);
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is specified but not all files belong to rootDir",
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/types/type.ts": "export type t = string;",
|
||||
"/src/tsconfig.json": JSON.stringify({
|
||||
compilerOptions: {
|
||||
outDir: "dist",
|
||||
rootDir: "src"
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios,
|
||||
}, ["/src/dist/index.js"]);
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is specified but not all files belong to rootDir and is composite",
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/types/type.ts": "export type t = string;",
|
||||
"/src/tsconfig.json": JSON.stringify({
|
||||
compilerOptions: {
|
||||
outDir: "dist",
|
||||
rootDir: "src",
|
||||
composite: true
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios,
|
||||
}, ["/src/dist/index.js", "/src/dist/index.d.ts"]);
|
||||
});
|
||||
}
|
||||
4
tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.d.ts
vendored
Normal file
4
tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/// <reference path="../../outdir/simple/fileC.d.ts" />
|
||||
declare class B {
|
||||
c: C;
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
/// <reference path="FolderC/fileC.d.ts" />
|
||||
declare class B {
|
||||
c: C;
|
||||
}
|
||||
@ -14,9 +14,9 @@
|
||||
"FolderA/FolderB/fileB.ts"
|
||||
],
|
||||
"emittedFiles": [
|
||||
"outdir/simple/FolderC/fileC.js",
|
||||
"outdir/simple/FolderC/fileC.d.ts",
|
||||
"outdir/simple/fileB.js",
|
||||
"outdir/simple/fileB.d.ts"
|
||||
"outdir/simple/fileC.js",
|
||||
"outdir/simple/fileC.d.ts",
|
||||
"FolderA/FolderB/fileB.js",
|
||||
"FolderA/FolderB/fileB.d.ts"
|
||||
]
|
||||
}
|
||||
4
tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.d.ts
vendored
Normal file
4
tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/// <reference path="../../outdir/simple/fileC.d.ts" />
|
||||
declare class B {
|
||||
c: C;
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
/// <reference path="FolderC/fileC.d.ts" />
|
||||
declare class B {
|
||||
c: C;
|
||||
}
|
||||
@ -14,9 +14,9 @@
|
||||
"FolderA/FolderB/fileB.ts"
|
||||
],
|
||||
"emittedFiles": [
|
||||
"outdir/simple/FolderC/fileC.js",
|
||||
"outdir/simple/FolderC/fileC.d.ts",
|
||||
"outdir/simple/fileB.js",
|
||||
"outdir/simple/fileB.d.ts"
|
||||
"outdir/simple/fileC.js",
|
||||
"outdir/simple/fileC.d.ts",
|
||||
"FolderA/FolderB/fileB.js",
|
||||
"FolderA/FolderB/fileB.d.ts"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
Input::
|
||||
//// [/lib/lib.d.ts]
|
||||
/// <reference no-default-lib="true"/>
|
||||
interface Boolean {}
|
||||
interface Function {}
|
||||
interface CallableFunction {}
|
||||
interface NewableFunction {}
|
||||
interface IArguments {}
|
||||
interface Number { toExponential: any; }
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
interface String { charAt: any; }
|
||||
interface Array<T> { length: number; [n: number]: T; }
|
||||
interface ReadonlyArray<T> {}
|
||||
declare const console: { log(msg: any): void; };
|
||||
|
||||
//// [/src/src/index.ts]
|
||||
export const x = 10;
|
||||
|
||||
//// [/src/tsconfig.json]
|
||||
{"compilerOptions":{"outDir":"dist","composite":true}}
|
||||
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:01:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:01:00 AM[0m] Project 'src/tsconfig.json' is out of date because output file 'src/dist/src/index.js' does not exist
|
||||
|
||||
[[90m12:01:00 AM[0m] Building project '/src/tsconfig.json'...
|
||||
|
||||
exitCode:: ExitStatus.Success
|
||||
|
||||
|
||||
//// [/src/dist/src/index.d.ts]
|
||||
export declare const x = 10;
|
||||
|
||||
|
||||
//// [/src/dist/src/index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.x = void 0;
|
||||
exports.x = 10;
|
||||
|
||||
|
||||
//// [/src/dist/tsconfig.tsbuildinfo]
|
||||
{
|
||||
"program": {
|
||||
"fileInfos": {
|
||||
"../../lib/lib.d.ts": {
|
||||
"version": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
|
||||
"signature": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
|
||||
"affectsGlobalScope": true
|
||||
},
|
||||
"../src/index.ts": {
|
||||
"version": "-10726455937-export const x = 10;",
|
||||
"signature": "-6057683066-export declare const x = 10;\r\n",
|
||||
"affectsGlobalScope": false
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"outDir": "./",
|
||||
"composite": true,
|
||||
"configFilePath": "../tsconfig.json"
|
||||
},
|
||||
"referencedMap": {},
|
||||
"exportedModulesMap": {},
|
||||
"semanticDiagnosticsPerFile": [
|
||||
"../../lib/lib.d.ts",
|
||||
"../src/index.ts"
|
||||
]
|
||||
},
|
||||
"version": "FakeTSVersion"
|
||||
}
|
||||
|
||||
|
||||
|
||||
Change:: no-change-run
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:04:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:04:00 AM[0m] Project 'src/tsconfig.json' is up to date because newest input 'src/src/index.ts' is older than oldest output 'src/dist/src/index.js'
|
||||
|
||||
exitCode:: ExitStatus.Success
|
||||
|
||||
|
||||
|
||||
|
||||
Change:: Normal build without change, that does not block emit on error to show files that get emitted
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc -p /src/tsconfig.json
|
||||
exitCode:: ExitStatus.Success
|
||||
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
Input::
|
||||
//// [/lib/lib.d.ts]
|
||||
/// <reference no-default-lib="true"/>
|
||||
interface Boolean {}
|
||||
interface Function {}
|
||||
interface CallableFunction {}
|
||||
interface NewableFunction {}
|
||||
interface IArguments {}
|
||||
interface Number { toExponential: any; }
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
interface String { charAt: any; }
|
||||
interface Array<T> { length: number; [n: number]: T; }
|
||||
interface ReadonlyArray<T> {}
|
||||
declare const console: { log(msg: any): void; };
|
||||
|
||||
//// [/src/src/index.ts]
|
||||
export const x = 10;
|
||||
|
||||
//// [/src/tsconfig.json]
|
||||
{"compilerOptions":{"outDir":"dist"}}
|
||||
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:01:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:01:00 AM[0m] Project 'src/tsconfig.json' is out of date because output file 'src/dist/index.js' does not exist
|
||||
|
||||
[[90m12:01:00 AM[0m] Building project '/src/tsconfig.json'...
|
||||
|
||||
exitCode:: ExitStatus.Success
|
||||
|
||||
|
||||
//// [/src/dist/index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.x = void 0;
|
||||
exports.x = 10;
|
||||
|
||||
|
||||
|
||||
|
||||
Change:: no-change-run
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:04:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:04:00 AM[0m] Project 'src/tsconfig.json' is up to date because newest input 'src/src/index.ts' is older than oldest output 'src/dist/index.js'
|
||||
|
||||
exitCode:: ExitStatus.Success
|
||||
|
||||
|
||||
|
||||
|
||||
Change:: Normal build without change, that does not block emit on error to show files that get emitted
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc -p /src/tsconfig.json
|
||||
exitCode:: ExitStatus.Success
|
||||
|
||||
|
||||
//// [/src/dist/index.js] file written with same contents
|
||||
@ -0,0 +1,137 @@
|
||||
Input::
|
||||
//// [/lib/lib.d.ts]
|
||||
/// <reference no-default-lib="true"/>
|
||||
interface Boolean {}
|
||||
interface Function {}
|
||||
interface CallableFunction {}
|
||||
interface NewableFunction {}
|
||||
interface IArguments {}
|
||||
interface Number { toExponential: any; }
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
interface String { charAt: any; }
|
||||
interface Array<T> { length: number; [n: number]: T; }
|
||||
interface ReadonlyArray<T> {}
|
||||
declare const console: { log(msg: any): void; };
|
||||
|
||||
//// [/src/src/index.ts]
|
||||
export const x = 10;
|
||||
|
||||
//// [/src/tsconfig.json]
|
||||
{"compilerOptions":{"outDir":"dist","rootDir":"src","composite":true}}
|
||||
|
||||
//// [/src/types/type.ts]
|
||||
export type t = string;
|
||||
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:01:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:01:00 AM[0m] Project 'src/tsconfig.json' is out of date because output file 'src/dist/index.js' does not exist
|
||||
|
||||
[[90m12:01:00 AM[0m] Building project '/src/tsconfig.json'...
|
||||
|
||||
[91merror[0m[90m TS6059: [0mFile '/src/types/type.ts' is not under 'rootDir' '/src/src'. 'rootDir' is expected to contain all source files.
|
||||
|
||||
|
||||
Found 1 error.
|
||||
|
||||
exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped
|
||||
|
||||
|
||||
|
||||
|
||||
Change:: no-change-run
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:04:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:04:00 AM[0m] Project 'src/tsconfig.json' is out of date because output file 'src/dist/index.js' does not exist
|
||||
|
||||
[[90m12:04:00 AM[0m] Building project '/src/tsconfig.json'...
|
||||
|
||||
[91merror[0m[90m TS6059: [0mFile '/src/types/type.ts' is not under 'rootDir' '/src/src'. 'rootDir' is expected to contain all source files.
|
||||
|
||||
|
||||
Found 1 error.
|
||||
|
||||
exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped
|
||||
|
||||
|
||||
|
||||
|
||||
Change:: Normal build without change, that does not block emit on error to show files that get emitted
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc -p /src/tsconfig.json
|
||||
[91merror[0m[90m TS6059: [0mFile '/src/types/type.ts' is not under 'rootDir' '/src/src'. 'rootDir' is expected to contain all source files.
|
||||
|
||||
|
||||
Found 1 error.
|
||||
|
||||
exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated
|
||||
|
||||
|
||||
//// [/src/dist/index.d.ts]
|
||||
export declare const x = 10;
|
||||
|
||||
|
||||
//// [/src/dist/index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.x = void 0;
|
||||
exports.x = 10;
|
||||
|
||||
|
||||
//// [/src/tsconfig.tsbuildinfo]
|
||||
{
|
||||
"program": {
|
||||
"fileInfos": {
|
||||
"../lib/lib.d.ts": {
|
||||
"version": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
|
||||
"signature": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
|
||||
"affectsGlobalScope": true
|
||||
},
|
||||
"./src/index.ts": {
|
||||
"version": "-10726455937-export const x = 10;",
|
||||
"signature": "-6057683066-export declare const x = 10;\r\n",
|
||||
"affectsGlobalScope": false
|
||||
},
|
||||
"./types/type.ts": {
|
||||
"version": "-4885977236-export type t = string;",
|
||||
"signature": "-4409762125-export declare type t = string;\r\n",
|
||||
"affectsGlobalScope": false
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"composite": true,
|
||||
"project": "./tsconfig.json",
|
||||
"configFilePath": "./tsconfig.json"
|
||||
},
|
||||
"referencedMap": {},
|
||||
"exportedModulesMap": {},
|
||||
"semanticDiagnosticsPerFile": []
|
||||
},
|
||||
"version": "FakeTSVersion"
|
||||
}
|
||||
|
||||
//// [/src/types/type.d.ts]
|
||||
export declare type t = string;
|
||||
|
||||
|
||||
//// [/src/types/type.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
Input::
|
||||
//// [/lib/lib.d.ts]
|
||||
/// <reference no-default-lib="true"/>
|
||||
interface Boolean {}
|
||||
interface Function {}
|
||||
interface CallableFunction {}
|
||||
interface NewableFunction {}
|
||||
interface IArguments {}
|
||||
interface Number { toExponential: any; }
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
interface String { charAt: any; }
|
||||
interface Array<T> { length: number; [n: number]: T; }
|
||||
interface ReadonlyArray<T> {}
|
||||
declare const console: { log(msg: any): void; };
|
||||
|
||||
//// [/src/src/index.ts]
|
||||
export const x = 10;
|
||||
|
||||
//// [/src/tsconfig.json]
|
||||
{"compilerOptions":{"outDir":"dist","rootDir":"src"}}
|
||||
|
||||
//// [/src/types/type.ts]
|
||||
export type t = string;
|
||||
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:01:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:01:00 AM[0m] Project 'src/tsconfig.json' is out of date because output file 'src/dist/index.js' does not exist
|
||||
|
||||
[[90m12:01:00 AM[0m] Building project '/src/tsconfig.json'...
|
||||
|
||||
[91merror[0m[90m TS6059: [0mFile '/src/types/type.ts' is not under 'rootDir' '/src/src'. 'rootDir' is expected to contain all source files.
|
||||
|
||||
|
||||
Found 1 error.
|
||||
|
||||
exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped
|
||||
|
||||
|
||||
|
||||
|
||||
Change:: no-change-run
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:04:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:04:00 AM[0m] Project 'src/tsconfig.json' is out of date because output file 'src/dist/index.js' does not exist
|
||||
|
||||
[[90m12:04:00 AM[0m] Building project '/src/tsconfig.json'...
|
||||
|
||||
[91merror[0m[90m TS6059: [0mFile '/src/types/type.ts' is not under 'rootDir' '/src/src'. 'rootDir' is expected to contain all source files.
|
||||
|
||||
|
||||
Found 1 error.
|
||||
|
||||
exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped
|
||||
|
||||
|
||||
|
||||
|
||||
Change:: Normal build without change, that does not block emit on error to show files that get emitted
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc -p /src/tsconfig.json
|
||||
[91merror[0m[90m TS6059: [0mFile '/src/types/type.ts' is not under 'rootDir' '/src/src'. 'rootDir' is expected to contain all source files.
|
||||
|
||||
|
||||
Found 1 error.
|
||||
|
||||
exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated
|
||||
|
||||
|
||||
//// [/src/dist/index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.x = void 0;
|
||||
exports.x = 10;
|
||||
|
||||
|
||||
//// [/src/types/type.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
Input::
|
||||
//// [/lib/lib.d.ts]
|
||||
/// <reference no-default-lib="true"/>
|
||||
interface Boolean {}
|
||||
interface Function {}
|
||||
interface CallableFunction {}
|
||||
interface NewableFunction {}
|
||||
interface IArguments {}
|
||||
interface Number { toExponential: any; }
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
interface String { charAt: any; }
|
||||
interface Array<T> { length: number; [n: number]: T; }
|
||||
interface ReadonlyArray<T> {}
|
||||
declare const console: { log(msg: any): void; };
|
||||
|
||||
//// [/src/src/index.ts]
|
||||
export const x = 10;
|
||||
|
||||
//// [/src/tsconfig.json]
|
||||
{"compilerOptions":{"outDir":"dist","rootDir":"src"}}
|
||||
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:01:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:01:00 AM[0m] Project 'src/tsconfig.json' is out of date because output file 'src/dist/index.js' does not exist
|
||||
|
||||
[[90m12:01:00 AM[0m] Building project '/src/tsconfig.json'...
|
||||
|
||||
exitCode:: ExitStatus.Success
|
||||
|
||||
|
||||
//// [/src/dist/index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.x = void 0;
|
||||
exports.x = 10;
|
||||
|
||||
|
||||
|
||||
|
||||
Change:: no-change-run
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc --b /src/tsconfig.json -v
|
||||
[[90m12:04:00 AM[0m] Projects in this build:
|
||||
* src/tsconfig.json
|
||||
|
||||
[[90m12:04:00 AM[0m] Project 'src/tsconfig.json' is up to date because newest input 'src/src/index.ts' is older than oldest output 'src/dist/index.js'
|
||||
|
||||
exitCode:: ExitStatus.Success
|
||||
|
||||
|
||||
|
||||
|
||||
Change:: Normal build without change, that does not block emit on error to show files that get emitted
|
||||
Input::
|
||||
|
||||
|
||||
Output::
|
||||
/lib/tsc -p /src/tsconfig.json
|
||||
exitCode:: ExitStatus.Success
|
||||
|
||||
|
||||
//// [/src/dist/index.js] file written with same contents
|
||||
@ -32,7 +32,7 @@ Output::
|
||||
[7m1[0m import { x } from "../b";
|
||||
[7m [0m [91m ~~~~~~[0m
|
||||
|
||||
[[90m12:00:34 AM[0m] Found 1 error. Watching for file changes.
|
||||
[[90m12:00:31 AM[0m] Found 1 error. Watching for file changes.
|
||||
|
||||
|
||||
|
||||
@ -69,14 +69,14 @@ FsWatchesRecursive::
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
//// [/user/username/projects/myproject/lib/b.js]
|
||||
//// [/user/username/projects/b.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.x = void 0;
|
||||
exports.x = 10;
|
||||
|
||||
|
||||
//// [/user/username/projects/myproject/lib/myproject/a.js]
|
||||
//// [/user/username/projects/myproject/lib/a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
|
||||
@ -93,14 +93,14 @@ import { x } from "../b";
|
||||
|
||||
Output::
|
||||
>> Screen clear
|
||||
[[90m12:00:38 AM[0m] File change detected. Starting incremental compilation...
|
||||
[[90m12:00:35 AM[0m] File change detected. Starting incremental compilation...
|
||||
|
||||
[96ma.ts[0m:[93m3[0m:[93m19[0m - [91merror[0m[90m TS6059: [0mFile '/user/username/projects/b.ts' is not under 'rootDir' '/user/username/projects/myproject'. 'rootDir' is expected to contain all source files.
|
||||
|
||||
[7m3[0m import { x } from "../b";
|
||||
[7m [0m [91m ~~~~~~[0m
|
||||
|
||||
[[90m12:00:42 AM[0m] Found 1 error. Watching for file changes.
|
||||
[[90m12:00:39 AM[0m] Found 1 error. Watching for file changes.
|
||||
|
||||
|
||||
|
||||
@ -135,4 +135,4 @@ FsWatchesRecursive::
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
//// [/user/username/projects/myproject/lib/myproject/a.js] file written with same contents
|
||||
//// [/user/username/projects/myproject/lib/a.js] file written with same contents
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user